diff --git a/Cargo.lock b/Cargo.lock index c4c96f1569b6f..eec27c64a02f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,9 +462,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" dependencies = [ "jobserver", "libc", @@ -1325,6 +1325,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650" + [[package]] name = "flate2" version = "1.1.2" @@ -3521,7 +3527,7 @@ dependencies = [ "ar_archive_writer", "bitflags", "bstr", - "cc", + "find-msvc-tools", "itertools", "libc", "object 0.37.3", diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 2dfbc58164323..e61764dff2b04 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,9 +8,8 @@ edition = "2024" ar_archive_writer = "0.5" bitflags = "2.4.1" bstr = "1.11.3" -# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_llvm`. -cc = "=1.2.16" +# `find-msvc-tools` updates often break things, so we pin it here. +find-msvc-tools = "=0.1.0" itertools = "0.12" pathdiff = "0.2.0" regex = "1.4" diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 48b01ea2df197..371f2c1a6a299 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -9,7 +9,7 @@ use std::path::{Path, PathBuf}; use std::process::{Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; -use cc::windows_registry; +use find_msvc_tools; use itertools::Itertools; use regex::Regex; use rustc_arena::TypedArena; @@ -877,9 +877,9 @@ fn link_natively( // All Microsoft `link.exe` linking ror codes are // four digit numbers in the range 1000 to 9999 inclusive if is_msvc_link_exe && (code < 1000 || code > 9999) { - let is_vs_installed = windows_registry::find_vs_version().is_ok(); + let is_vs_installed = find_msvc_tools::find_vs_version().is_ok(); let has_linker = - windows_registry::find_tool(&sess.target.arch, "link.exe").is_some(); + find_msvc_tools::find_tool(&sess.target.arch, "link.exe").is_some(); sess.dcx().emit_note(errors::LinkExeUnexpectedError); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a2efd420a327a..dff9f1eb06288 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -4,7 +4,7 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::{env, io, iter, mem, str}; -use cc::windows_registry; +use find_msvc_tools; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::{ find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, @@ -53,7 +53,7 @@ pub(crate) fn get_linker<'a>( self_contained: bool, target_cpu: &'a str, ) -> Box { - let msvc_tool = windows_registry::find_tool(&sess.target.arch, "link.exe"); + let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe"); // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle @@ -117,7 +117,6 @@ pub(crate) fn get_linker<'a>( if sess.target.is_like_msvc && let Some(ref tool) = msvc_tool { - cmd.args(tool.args()); for (k, v) in tool.env() { if k == "PATH" { new_path.extend(env::split_paths(v)); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a652e08905a55..7adbee7ff2855 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2585,12 +2585,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .filter(|item| item.is_fn() && !item.is_method()) .filter_map(|item| { // Only assoc fns that return `Self` - let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder(); - let ret_ty = fn_sig.output(); - let ret_ty = self.tcx.normalize_erasing_late_bound_regions( - self.typing_env(self.param_env), - ret_ty, - ); + let fn_sig = self + .tcx + .fn_sig(item.def_id) + .instantiate(self.tcx, self.fresh_args_for_item(span, item.def_id)); + let ret_ty = self.tcx.instantiate_bound_regions_with_erased(fn_sig.output()); if !self.can_eq(self.param_env, ret_ty, adt_ty) { return None; } diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index cd352ce3d0f4f..45011f9b446cb 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -10,9 +10,8 @@ libc = "0.2.73" [build-dependencies] # tidy-alphabetical-start -# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_codegen_ssa`. -cc = "=1.2.16" +# `cc` updates often break things, so we pin it here. +cc = "=1.2.33" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index d567ad401bb1f..9213d73e24eac 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -8,16 +8,16 @@ use crate::spec::HasTargetSpec; #[derive(Copy, Clone)] enum RegPassKind { - Float(Reg), - Integer(Reg), + Float { offset_from_start: Size, ty: Reg }, + Integer { offset_from_start: Size, ty: Reg }, Unknown, } #[derive(Copy, Clone)] enum FloatConv { - FloatPair(Reg, Reg), + FloatPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, Float(Reg), - MixedPair(Reg, Reg), + MixedPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, } #[derive(Copy, Clone)] @@ -37,6 +37,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( flen: u64, field1_kind: &mut RegPassKind, field2_kind: &mut RegPassKind, + offset_from_start: Size, ) -> Result<(), CannotUseFpConv> where Ty: TyAbiInterface<'a, C> + Copy, @@ -49,16 +50,16 @@ where } match (*field1_kind, *field2_kind) { (RegPassKind::Unknown, _) => { - *field1_kind = RegPassKind::Integer(Reg { - kind: RegKind::Integer, - size: arg_layout.size, - }); + *field1_kind = RegPassKind::Integer { + offset_from_start, + ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, + }; } - (RegPassKind::Float(_), RegPassKind::Unknown) => { - *field2_kind = RegPassKind::Integer(Reg { - kind: RegKind::Integer, - size: arg_layout.size, - }); + (RegPassKind::Float { .. }, RegPassKind::Unknown) => { + *field2_kind = RegPassKind::Integer { + offset_from_start, + ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, + }; } _ => return Err(CannotUseFpConv), } @@ -69,12 +70,16 @@ where } match (*field1_kind, *field2_kind) { (RegPassKind::Unknown, _) => { - *field1_kind = - RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + *field1_kind = RegPassKind::Float { + offset_from_start, + ty: Reg { kind: RegKind::Float, size: arg_layout.size }, + }; } (_, RegPassKind::Unknown) => { - *field2_kind = - RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + *field2_kind = RegPassKind::Float { + offset_from_start, + ty: Reg { kind: RegKind::Float, size: arg_layout.size }, + }; } _ => return Err(CannotUseFpConv), } @@ -96,13 +101,14 @@ where flen, field1_kind, field2_kind, + offset_from_start, ); } return Err(CannotUseFpConv); } } FieldsShape::Array { count, .. } => { - for _ in 0..count { + for i in 0..count { let elem_layout = arg_layout.field(cx, 0); should_use_fp_conv_helper( cx, @@ -111,6 +117,7 @@ where flen, field1_kind, field2_kind, + offset_from_start + elem_layout.size * i, )?; } } @@ -121,7 +128,15 @@ where } for i in arg_layout.fields.index_by_increasing_offset() { let field = arg_layout.field(cx, i); - should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; + should_use_fp_conv_helper( + cx, + &field, + xlen, + flen, + field1_kind, + field2_kind, + offset_from_start + arg_layout.fields.offset(i), + )?; } } }, @@ -140,14 +155,52 @@ where { let mut field1_kind = RegPassKind::Unknown; let mut field2_kind = RegPassKind::Unknown; - if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { + if should_use_fp_conv_helper( + cx, + arg, + xlen, + flen, + &mut field1_kind, + &mut field2_kind, + Size::ZERO, + ) + .is_err() + { return None; } match (field1_kind, field2_kind) { - (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), - (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), - (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), - (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), + ( + RegPassKind::Integer { offset_from_start, .. } + | RegPassKind::Float { offset_from_start, .. }, + _, + ) if offset_from_start != Size::ZERO => { + panic!("type {:?} has a first field with non-zero offset {offset_from_start:?}", arg.ty) + } + ( + RegPassKind::Integer { ty: first_ty, .. }, + RegPassKind::Float { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::MixedPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + ( + RegPassKind::Float { ty: first_ty, .. }, + RegPassKind::Integer { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::MixedPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + ( + RegPassKind::Float { ty: first_ty, .. }, + RegPassKind::Float { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::FloatPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + (RegPassKind::Float { ty, .. }, RegPassKind::Unknown) => Some(FloatConv::Float(ty)), _ => None, } } @@ -165,11 +218,19 @@ where FloatConv::Float(f) => { arg.cast_to(f); } - FloatConv::FloatPair(l, r) => { - arg.cast_to(CastTarget::pair(l, r)); + FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty } => { + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); } - FloatConv::MixedPair(l, r) => { - arg.cast_to(CastTarget::pair(l, r)); + FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty } => { + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); } } return false; @@ -233,15 +294,27 @@ fn classify_arg<'a, Ty, C>( arg.cast_to(f); return; } - Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { + Some(FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty }) + if *avail_fprs >= 2 => + { *avail_fprs -= 2; - arg.cast_to(CastTarget::pair(l, r)); + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); return; } - Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { + Some(FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty }) + if *avail_fprs >= 1 && *avail_gprs >= 1 => + { *avail_gprs -= 1; *avail_fprs -= 1; - arg.cast_to(CastTarget::pair(l, r)); + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); return; } _ => (), diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs index c173d7f0ae01f..4267fef50f83c 100644 --- a/library/coretests/tests/floats/f128.rs +++ b/library/coretests/tests/floats/f128.rs @@ -1,7 +1,9 @@ // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(target_has_reliable_f128)] -use super::{assert_approx_eq, assert_biteq}; +#[cfg(any(miri, target_has_reliable_f128_math))] +use super::assert_approx_eq; +use super::assert_biteq; // Note these tolerances make sense around zero, but not for more extreme exponents. @@ -74,25 +76,6 @@ fn test_float_bits_conv() { assert_eq!(f128::from_bits(masked_nan2).to_bits(), masked_nan2); } -#[test] -fn test_algebraic() { - let a: f128 = 123.0; - let b: f128 = 456.0; - - // Check that individual operations match their primitive counterparts. - // - // This is a check of current implementations and does NOT imply any form of - // guarantee about future behavior. The compiler reserves the right to make - // these operations inexact matches in the future. - let eps = if cfg!(miri) { 1e-6 } else { 0.0 }; - - assert_approx_eq!(a.algebraic_add(b), a + b, eps); - assert_approx_eq!(a.algebraic_sub(b), a - b, eps); - assert_approx_eq!(a.algebraic_mul(b), a * b, eps); - assert_approx_eq!(a.algebraic_div(b), a / b, eps); - assert_approx_eq!(a.algebraic_rem(b), a % b, eps); -} - #[test] fn test_from() { assert_biteq!(f128::from(false), 0.0); diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs index c12de7221baa7..d2818a6d76897 100644 --- a/library/coretests/tests/floats/f16.rs +++ b/library/coretests/tests/floats/f16.rs @@ -73,27 +73,6 @@ fn test_float_bits_conv() { assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2); } -#[test] -fn test_algebraic() { - let a: f16 = 123.0; - let b: f16 = 456.0; - - // Check that individual operations match their primitive counterparts. - // - // This is a check of current implementations and does NOT imply any form of - // guarantee about future behavior. The compiler reserves the right to make - // these operations inexact matches in the future. - let eps_add = if cfg!(miri) { 1e1 } else { 0.0 }; - let eps_mul = if cfg!(miri) { 1e3 } else { 0.0 }; - let eps_div = if cfg!(miri) { 1e0 } else { 0.0 }; - - assert_approx_eq!(a.algebraic_add(b), a + b, eps_add); - assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add); - assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul); - assert_approx_eq!(a.algebraic_div(b), a / b, eps_div); - assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div); -} - #[test] fn test_from() { assert_biteq!(f16::from(false), 0.0); diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs index b79295f470def..7b25f354da428 100644 --- a/library/coretests/tests/floats/f32.rs +++ b/library/coretests/tests/floats/f32.rs @@ -1,6 +1,6 @@ use core::f32; -use super::{assert_approx_eq, assert_biteq}; +use super::assert_biteq; /// First pattern over the mantissa const NAN_MASK1: u32 = 0x002a_aaaa; @@ -47,24 +47,3 @@ fn test_float_bits_conv() { assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1); assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2); } - -#[test] -fn test_algebraic() { - let a: f32 = 123.0; - let b: f32 = 456.0; - - // Check that individual operations match their primitive counterparts. - // - // This is a check of current implementations and does NOT imply any form of - // guarantee about future behavior. The compiler reserves the right to make - // these operations inexact matches in the future. - let eps_add = if cfg!(miri) { 1e-3 } else { 0.0 }; - let eps_mul = if cfg!(miri) { 1e-1 } else { 0.0 }; - let eps_div = if cfg!(miri) { 1e-4 } else { 0.0 }; - - assert_approx_eq!(a.algebraic_add(b), a + b, eps_add); - assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add); - assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul); - assert_approx_eq!(a.algebraic_div(b), a / b, eps_div); - assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div); -} diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs index a254058632867..099d85627a346 100644 --- a/library/coretests/tests/floats/f64.rs +++ b/library/coretests/tests/floats/f64.rs @@ -1,6 +1,6 @@ use core::f64; -use super::{assert_approx_eq, assert_biteq}; +use super::assert_biteq; /// First pattern over the mantissa const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa; @@ -46,22 +46,3 @@ fn test_float_bits_conv() { assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1); assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2); } - -#[test] -fn test_algebraic() { - let a: f64 = 123.0; - let b: f64 = 456.0; - - // Check that individual operations match their primitive counterparts. - // - // This is a check of current implementations and does NOT imply any form of - // guarantee about future behavior. The compiler reserves the right to make - // these operations inexact matches in the future. - let eps = if cfg!(miri) { 1e-6 } else { 0.0 }; - - assert_approx_eq!(a.algebraic_add(b), a + b, eps); - assert_approx_eq!(a.algebraic_sub(b), a - b, eps); - assert_approx_eq!(a.algebraic_mul(b), a * b, eps); - assert_approx_eq!(a.algebraic_div(b), a / b, eps); - assert_approx_eq!(a.algebraic_rem(b), a % b, eps); -} diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 5f59cb9cce379..c0439845a4a48 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -27,6 +27,9 @@ trait TestableFloat: Sized { const NAN_MASK1: Self::Int; /// Second pattern over the mantissa const NAN_MASK2: Self::Int; + const EPS_ADD: Self; + const EPS_MUL: Self; + const EPS_DIV: Self; } impl TestableFloat for f16 { @@ -44,6 +47,9 @@ impl TestableFloat for f16 { const MAX_DOWN: Self = Self::from_bits(0x7bfe); const NAN_MASK1: Self::Int = 0x02aa; const NAN_MASK2: Self::Int = 0x0155; + const EPS_ADD: Self = if cfg!(miri) { 1e1 } else { 0.0 }; + const EPS_MUL: Self = if cfg!(miri) { 1e3 } else { 0.0 }; + const EPS_DIV: Self = if cfg!(miri) { 1e0 } else { 0.0 }; } impl TestableFloat for f32 { @@ -63,6 +69,9 @@ impl TestableFloat for f32 { const MAX_DOWN: Self = Self::from_bits(0x7f7f_fffe); const NAN_MASK1: Self::Int = 0x002a_aaaa; const NAN_MASK2: Self::Int = 0x0055_5555; + const EPS_ADD: Self = if cfg!(miri) { 1e-3 } else { 0.0 }; + const EPS_MUL: Self = if cfg!(miri) { 1e-1 } else { 0.0 }; + const EPS_DIV: Self = if cfg!(miri) { 1e-4 } else { 0.0 }; } impl TestableFloat for f64 { @@ -78,6 +87,9 @@ impl TestableFloat for f64 { const MAX_DOWN: Self = Self::from_bits(0x7fef_ffff_ffff_fffe); const NAN_MASK1: Self::Int = 0x000a_aaaa_aaaa_aaaa; const NAN_MASK2: Self::Int = 0x0005_5555_5555_5555; + const EPS_ADD: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; + const EPS_MUL: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; + const EPS_DIV: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; } impl TestableFloat for f128 { @@ -93,6 +105,9 @@ impl TestableFloat for f128 { const MAX_DOWN: Self = Self::from_bits(0x7ffefffffffffffffffffffffffffffe); const NAN_MASK1: Self::Int = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa; const NAN_MASK2: Self::Int = 0x00005555555555555555555555555555; + const EPS_ADD: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; + const EPS_MUL: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; + const EPS_DIV: Self = if cfg!(miri) { 1e-6 } else { 0.0 }; } /// Determine the tolerance for values of the argument type. @@ -1440,3 +1455,27 @@ float_test! { assert_biteq!(neg_inf.to_radians(), neg_inf); } } + +float_test! { + name: to_algebraic, + attrs: { + f16: #[cfg(target_has_reliable_f16)], + f128: #[cfg(target_has_reliable_f128)], + }, + test { + let a: Float = 123.0; + let b: Float = 456.0; + + // Check that individual operations match their primitive counterparts. + // + // This is a check of current implementations and does NOT imply any form of + // guarantee about future behavior. The compiler reserves the right to make + // these operations inexact matches in the future. + + assert_approx_eq!(a.algebraic_add(b), a + b, Float::EPS_ADD); + assert_approx_eq!(a.algebraic_sub(b), a - b, Float::EPS_ADD); + assert_approx_eq!(a.algebraic_mul(b), a * b, Float::EPS_MUL); + assert_approx_eq!(a.algebraic_div(b), a / b, Float::EPS_DIV); + assert_approx_eq!(a.algebraic_rem(b), a % b, Float::EPS_DIV); + } +} diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs index 314f226f07beb..7436e4d9de4da 100644 --- a/library/std/src/sys/stdio/mod.rs +++ b/library/std/src/sys/stdio/mod.rs @@ -29,9 +29,13 @@ cfg_select! { mod uefi; pub use uefi::*; } - target_os = "wasi" => { - mod wasi; - pub use wasi::*; + all(target_os = "wasi", target_env = "p1") => { + mod wasip1; + pub use wasip1::*; + } + all(target_os = "wasi", target_env = "p2") => { + mod wasip2; + pub use wasip2::*; } target_os = "xous" => { mod xous; diff --git a/library/std/src/sys/stdio/wasi.rs b/library/std/src/sys/stdio/wasip1.rs similarity index 100% rename from library/std/src/sys/stdio/wasi.rs rename to library/std/src/sys/stdio/wasip1.rs diff --git a/library/std/src/sys/stdio/wasip2.rs b/library/std/src/sys/stdio/wasip2.rs new file mode 100644 index 0000000000000..1fcb49a083dd0 --- /dev/null +++ b/library/std/src/sys/stdio/wasip2.rs @@ -0,0 +1,120 @@ +use wasip2::cli; +use wasip2::io::streams::{Error, InputStream, OutputStream, StreamError}; + +use crate::io::{self, BorrowedBuf, BorrowedCursor}; + +pub struct Stdin(Option); +pub struct Stdout(Option); +pub struct Stderr(Option); + +fn error_to_io(err: Error) -> io::Error { + // There exists a function in `wasi:filesystem` to optionally acquire an + // error code from an error, but the streams in use in this module are + // exclusively used with stdio meaning that a filesystem error is not + // possible here. + // + // In lieu of an error code, which WASIp2 does not specify, this instead + // carries along the `to_debug_string` implementation that the host + // supplies. If this becomes too expensive in the future this could also + // become `io::Error::from_raw_os_error(libc::EIO)` or similar. + io::Error::new(io::ErrorKind::Other, err.to_debug_string()) +} + +impl Stdin { + pub const fn new() -> Stdin { + Stdin(None) + } + + fn stream(&mut self) -> &InputStream { + self.0.get_or_insert_with(cli::stdin::get_stdin) + } +} + +impl io::Read for Stdin { + fn read(&mut self, data: &mut [u8]) -> io::Result { + let mut buf = BorrowedBuf::from(data); + self.read_buf(buf.unfilled())?; + Ok(buf.len()) + } + + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + match self.stream().blocking_read(u64::try_from(buf.capacity()).unwrap()) { + Ok(result) => { + buf.append(&result); + Ok(()) + } + Err(StreamError::Closed) => Ok(()), + Err(StreamError::LastOperationFailed(e)) => Err(error_to_io(e)), + } + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout(None) + } + + fn stream(&mut self) -> &OutputStream { + self.0.get_or_insert_with(cli::stdout::get_stdout) + } +} + +fn write(stream: &OutputStream, buf: &[u8]) -> io::Result { + // WASIp2's `blocking_write_and_flush` function is defined as accepting no + // more than 4096 bytes. Larger writes can be issued by manually using + // `check_write`, `write`, and `blocking_flush`, but for now just go ahead + // and use `blocking_write_and_flush` and report a short write and let a + // higher level loop over the result. + const MAX: usize = 4096; + let buf = &buf[..buf.len().min(MAX)]; + match stream.blocking_write_and_flush(buf) { + Ok(()) => Ok(buf.len()), + Err(StreamError::Closed) => Ok(0), + Err(StreamError::LastOperationFailed(e)) => Err(error_to_io(e)), + } +} + +impl io::Write for Stdout { + fn write(&mut self, data: &[u8]) -> io::Result { + write(self.stream(), data) + } + + fn flush(&mut self) -> io::Result<()> { + // Note that `OutputStream` has a `flush` function but for stdio all + // writes are accompanied with a flush which means that this flush + // doesn't need to do anything. + Ok(()) + } +} + +impl Stderr { + pub const fn new() -> Stderr { + Stderr(None) + } + + fn stream(&mut self) -> &OutputStream { + self.0.get_or_insert_with(cli::stderr::get_stderr) + } +} + +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { + write(self.stream(), data) + } + + fn flush(&mut self) -> io::Result<()> { + // See `Stdout::flush` for why this is a noop. + Ok(()) + } +} + +pub const STDIN_BUF_SIZE: usize = crate::sys::io::DEFAULT_BUF_SIZE; + +pub fn is_ebadf(_err: &io::Error) -> bool { + // WASIp2 stdio streams are always available so ebadf never shows up. + false +} + +pub fn panic_output() -> Option { + Some(Stderr::new()) +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 560f11ecf50ec..93410997f486f 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -275,6 +275,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", + "find-msvc-tools", "flate2", "fluent-bundle", "fluent-langneg", diff --git a/tests/assembly-llvm/loongarch-float-struct-abi.rs b/tests/assembly-llvm/loongarch-float-struct-abi.rs new file mode 100644 index 0000000000000..4991004fc05a8 --- /dev/null +++ b/tests/assembly-llvm/loongarch-float-struct-abi.rs @@ -0,0 +1,134 @@ +//@ add-core-stubs +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu +//@ needs-llvm-components: loongarch + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[repr(C, align(64))] +struct Aligned(f64); + +#[repr(C)] +struct Padded(u8, Aligned); + +#[repr(C, packed)] +struct Packed(u8, f32); + +impl Copy for Aligned {} +impl Copy for Padded {} +impl Copy for Packed {} + +extern "C" { + fn take_padded(x: Padded); + fn get_padded() -> Padded; + fn take_packed(x: Packed); + fn get_packed() -> Packed; +} + +// CHECK-LABEL: pass_padded +#[unsafe(no_mangle)] +extern "C" fn pass_padded(out: &mut Padded, x: Padded) { + // CHECK: st.b $a1, $a0, 0 + // CHECK-NEXT: fst.d $fa0, $a0, 64 + // CHECK-NEXT: ret + *out = x; +} + +// CHECK-LABEL: ret_padded +#[unsafe(no_mangle)] +extern "C" fn ret_padded(x: &Padded) -> Padded { + // CHECK: fld.d $fa0, $a0, 64 + // CHECK-NEXT: ld.b $a0, $a0, 0 + // CHECK-NEXT: ret + *x +} + +#[unsafe(no_mangle)] +extern "C" fn call_padded(x: &Padded) { + // CHECK: fld.d $fa0, $a0, 64 + // CHECK-NEXT: ld.b $a0, $a0, 0 + // CHECK-NEXT: pcaddu18i $t8, %call36(take_padded) + // CHECK-NEXT: jr $t8 + unsafe { + take_padded(*x); + } +} + +#[unsafe(no_mangle)] +extern "C" fn receive_padded(out: &mut Padded) { + // CHECK: addi.d $sp, $sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: st.d $ra, $sp, [[#%d,RA_SPILL:]] + // CHECK-NEXT: st.d [[TEMP:.*]], $sp, [[#%d,TEMP_SPILL:]] + // CHECK-NEXT: .cfi_offset 1, [[#%d,RA_SPILL - 16]] + // CHECK-NEXT: .cfi_offset [[#%d,TEMP_NUM:]], [[#%d,TEMP_SPILL - 16]] + // CHECK-NEXT: move [[TEMP]], $a0 + // CHECK-NEXT: pcaddu18i $ra, %call36(get_padded) + // CHECK-NEXT: jirl $ra, $ra, 0 + // CHECK-NEXT: st.b $a0, [[TEMP]], 0 + // CHECK-NEXT: fst.d $fa0, [[TEMP]], 64 + // CHECK-NEXT: ld.d [[TEMP]], $sp, [[#%d,TEMP_SPILL]] + // CHECK-NEXT: ld.d $ra, $sp, [[#%d,RA_SPILL]] + // CHECK: addi.d $sp, $sp, 16 + // CHECK: ret + unsafe { + *out = get_padded(); + } +} + +// CHECK-LABEL: pass_packed +#[unsafe(no_mangle)] +extern "C" fn pass_packed(out: &mut Packed, x: Packed) { + // CHECK: st.b $a1, $a0, 0 + // CHECK-NEXT: fst.s $fa0, $a0, 1 + // CHECK-NEXT: ret + *out = x; +} + +// CHECK-LABEL: ret_packed +#[unsafe(no_mangle)] +extern "C" fn ret_packed(x: &Packed) -> Packed { + // CHECK: fld.s $fa0, $a0, 1 + // CHECK-NEXT: ld.b $a0, $a0, 0 + // CHECK-NEXT: ret + *x +} + +#[unsafe(no_mangle)] +extern "C" fn call_packed(x: &Packed) { + // CHECK: fld.s $fa0, $a0, 1 + // CHECK-NEXT: ld.b $a0, $a0, 0 + // CHECK-NEXT: pcaddu18i $t8, %call36(take_packed) + // CHECK-NEXT: jr $t8 + unsafe { + take_packed(*x); + } +} + +#[unsafe(no_mangle)] +extern "C" fn receive_packed(out: &mut Packed) { + // CHECK: addi.d $sp, $sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: st.d $ra, $sp, [[#%d,RA_SPILL:]] + // CHECK-NEXT: st.d [[TEMP:.*]], $sp, [[#%d,TEMP_SPILL:]] + // CHECK-NEXT: .cfi_offset 1, [[#%d,RA_SPILL - 16]] + // CHECK-NEXT: .cfi_offset [[#%d,TEMP_NUM:]], [[#%d,TEMP_SPILL - 16]] + // CHECK-NEXT: move [[TEMP]], $a0 + // CHECK-NEXT: pcaddu18i $ra, %call36(get_packed) + // CHECK-NEXT: jirl $ra, $ra, 0 + // CHECK-NEXT: st.b $a0, [[TEMP]], 0 + // CHECK-NEXT: fst.s $fa0, [[TEMP]], 1 + // CHECK-NEXT: ld.d [[TEMP]], $sp, [[#%d,TEMP_SPILL]] + // CHECK-NEXT: ld.d $ra, $sp, [[#%d,RA_SPILL]] + // CHECK: addi.d $sp, $sp, 16 + // CHECK: ret + unsafe { + *out = get_packed(); + } +} diff --git a/tests/codegen-llvm/cast-target-abi.rs b/tests/codegen-llvm/cast-target-abi.rs index 28d3ad5f61c7f..090de00df9367 100644 --- a/tests/codegen-llvm/cast-target-abi.rs +++ b/tests/codegen-llvm/cast-target-abi.rs @@ -171,7 +171,15 @@ pub extern "C" fn receives_doubledouble(x: DoubleDouble) { // CHECK: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] - // CHECK: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = extractvalue [[ABI_TYPE]] [[ABI_VALUE:%.+]], 0 + // loongarch64: [[ABI_VALUE_1:%.+]] = extractvalue [[ABI_TYPE]] [[ABI_VALUE:%.+]], 1 + // loongarch64: store double [[ABI_VALUE_0]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: store double [[ABI_VALUE_1]], ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] + // powerpc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // x86_64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) } @@ -190,7 +198,11 @@ pub extern "C" fn returns_doubledouble() -> DoubleDouble { // x86_64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x double\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = load double, ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: [[ABI_VALUE_1:%.+]] = load double, ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_2:%.+]] = insertvalue [[ABI_TYPE:{ double, double }]] poison, double [[ABI_VALUE_0]], 0 + // loongarch64: [[ABI_VALUE:%.+]] = insertvalue { double, double } [[ABI_VALUE_2]], double [[ABI_VALUE_1]], 1 // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -269,7 +281,11 @@ pub extern "C" fn receives_doublefloat(x: DoubleFloat) { // x86_64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = extractvalue { double, float } [[ABI_VALUE]], 0 + // loongarch64: [[ABI_VALUE_1:%.+]] = extractvalue { double, float } [[ABI_VALUE]], 1 + // loongarch64: store double [[ABI_VALUE_0]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: store float [[ABI_VALUE_1]], ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] // powerpc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -297,7 +313,11 @@ pub extern "C" fn returns_doublefloat() -> DoubleFloat { // x86_64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, float }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = load double, ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: [[ABI_VALUE_1:%.+]] = load float, ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_2:%.+]] = insertvalue [[ABI_TYPE:{ double, float }]] poison, double [[ABI_VALUE_0]], 0 + // loongarch64: [[ABI_VALUE:%.+]] = insertvalue { double, float } [[ABI_VALUE_2]], float [[ABI_VALUE_1]], 1 // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: ret [[ABI_TYPE]] [[ABI_VALUE]] @@ -429,7 +449,11 @@ pub fn call_doubledouble() { // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x double\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = load double, ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: [[ABI_VALUE_1:%.+]] = load double, ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_2:%.+]] = insertvalue [[ABI_TYPE:{ double, double }]] poison, double [[ABI_VALUE_0]], 0 + // loongarch64: [[ABI_VALUE:%.+]] = insertvalue { double, double } [[ABI_VALUE_2]], double [[ABI_VALUE_1]], 1 // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -465,7 +489,11 @@ pub fn return_doubledouble() -> DoubleDouble { // x86_64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doubledouble() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = extractvalue { double, double } [[ABI_VALUE]], 0 + // loongarch64: [[ABI_VALUE_1:%.+]] = extractvalue { double, double } [[ABI_VALUE]], 1 + // loongarch64: store double [[ABI_VALUE_0]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: store double [[ABI_VALUE_1]], ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -500,7 +528,11 @@ pub fn call_doublefloat() { // x86_64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, float }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = load double, ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: [[ABI_VALUE_1:%.+]] = load float, ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_2:%.+]] = insertvalue [[ABI_TYPE:{ double, float }]] poison, double [[ABI_VALUE_0]], 0 + // loongarch64: [[ABI_VALUE:%.+]] = insertvalue { double, float } [[ABI_VALUE_2]], float [[ABI_VALUE_1]], 1 // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -540,7 +572,11 @@ pub fn return_doublefloat() -> DoubleFloat { // x86_64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doublefloat() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE_0:%.+]] = extractvalue { double, float } [[ABI_VALUE]], 0 + // loongarch64: [[ABI_VALUE_1:%.+]] = extractvalue { double, float } [[ABI_VALUE]], 1 + // loongarch64: store double [[ABI_VALUE_0]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_ALLOCA_1:%.+]] = getelementptr inbounds i8, ptr [[ABI_ALLOCA]], i64 8 + // loongarch64: store float [[ABI_VALUE_1]], ptr [[ABI_ALLOCA_1]], align [[ABI_ALIGN]] // x86_64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) diff --git a/tests/codegen-llvm/loongarch-abi/cast-local-large-enough.rs b/tests/codegen-llvm/loongarch-abi/cast-local-large-enough.rs new file mode 100644 index 0000000000000..e5a0e4cd3a2c4 --- /dev/null +++ b/tests/codegen-llvm/loongarch-abi/cast-local-large-enough.rs @@ -0,0 +1,44 @@ +//@ add-core-stubs +//@ compile-flags: -Copt-level=0 -Cdebuginfo=0 --target loongarch64-unknown-linux-gnu +//@ needs-llvm-components: loongarch + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[repr(C, align(64))] +struct Aligned(f64); + +#[repr(C, align(64))] +struct AlignedPair(f32, f64); + +impl Copy for Aligned {} +impl Copy for AlignedPair {} + +// CHECK-LABEL: define double @read_aligned +#[unsafe(no_mangle)] +pub extern "C" fn read_aligned(x: &Aligned) -> Aligned { + // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) + // CHECK-NEXT: %[[RES:.*]] = load double, ptr %[[TEMP]], align 64 + // CHECK-NEXT: ret double %[[RES]] + *x +} + +// CHECK-LABEL: define { float, double } @read_aligned_pair +#[unsafe(no_mangle)] +pub extern "C" fn read_aligned_pair(x: &AlignedPair) -> AlignedPair { + // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) + // CHECK-NEXT: %[[FIRST:.*]] = load float, ptr %[[TEMP]], align 64 + // CHECK-NEXT: %[[SECOND_PTR:.*]] = getelementptr inbounds i8, ptr %[[TEMP]], i64 8 + // CHECK-NEXT: %[[SECOND:.*]] = load double, ptr %[[SECOND_PTR]], align 8 + // CHECK-NEXT: %[[RES1:.*]] = insertvalue { float, double } poison, float %[[FIRST]], 0 + // CHECK-NEXT: %[[RES2:.*]] = insertvalue { float, double } %[[RES1]], double %[[SECOND]], 1 + // CHECK-NEXT: ret { float, double } %[[RES2]] + *x +} diff --git a/tests/ui/privacy/suggest-box-new.rs b/tests/ui/privacy/suggest-box-new.rs index 7125285fc7764..ff585387020e4 100644 --- a/tests/ui/privacy/suggest-box-new.rs +++ b/tests/ui/privacy/suggest-box-new.rs @@ -16,4 +16,7 @@ fn main() { let _ = std::collections::HashMap {}; //~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields let _ = Box {}; //~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields + + // test that we properly instantiate the parameter of `Box::::new` with an inference variable + let _ = Box:: {}; //~ ERROR cannot construct `Box` with struct literal syntax due to private fields } diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr index 2b48e9046bf03..37b2989dcc148 100644 --- a/tests/ui/privacy/suggest-box-new.stderr +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -118,13 +118,41 @@ LL + let _ = Box::new_zeroed(); LL - let _ = Box {}; LL + let _ = Box::new_in(_, _); | - = and 12 other candidates + = and 13 other candidates help: consider using the `Default` trait | LL - let _ = Box {}; LL + let _ = ::default(); | -error: aborting due to 4 previous errors +error: cannot construct `Box` with struct literal syntax due to private fields + --> $DIR/suggest-box-new.rs:21:13 + | +LL | let _ = Box:: {}; + | ^^^^^^^^^^ + | + = note: private fields `0` and `1` that were not provided +help: you might have meant to use an associated function to build this type + | +LL - let _ = Box:: {}; +LL + let _ = Box::::new(_); + | +LL - let _ = Box:: {}; +LL + let _ = Box::::new_in(_, _); + | +LL - let _ = Box:: {}; +LL + let _ = Box::::into_inner(_); + | +LL - let _ = Box:: {}; +LL + let _ = Box::::write(_, _); + | + = and 4 other candidates +help: consider using the `Default` trait + | +LL - let _ = Box:: {}; +LL + let _ = as std::default::Default>::default(); + | + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/suggest-new-projection-ice.rs b/tests/ui/privacy/suggest-new-projection-ice.rs new file mode 100644 index 0000000000000..41ac27508e8ac --- /dev/null +++ b/tests/ui/privacy/suggest-new-projection-ice.rs @@ -0,0 +1,19 @@ +//! Regression test for . +//! Ensure that we don't ICE when an associated function returns an associated type. + +mod m { + pub trait Project { + type Assoc; + } + pub struct Foo { + _priv: (), + } + impl Foo { + fn new() -> T::Assoc { + todo!() + } + } +} +fn main() { + let _ = m::Foo {}; //~ ERROR: cannot construct `Foo` +} diff --git a/tests/ui/privacy/suggest-new-projection-ice.stderr b/tests/ui/privacy/suggest-new-projection-ice.stderr new file mode 100644 index 0000000000000..4700772096b93 --- /dev/null +++ b/tests/ui/privacy/suggest-new-projection-ice.stderr @@ -0,0 +1,10 @@ +error: cannot construct `Foo` with struct literal syntax due to private fields + --> $DIR/suggest-new-projection-ice.rs:18:13 + | +LL | let _ = m::Foo {}; + | ^^^^^^ + | + = note: private field `_priv` that was not provided + +error: aborting due to 1 previous error + diff --git a/tests/ui/suggestions/multi-suggestion.ascii.stderr b/tests/ui/suggestions/multi-suggestion.ascii.stderr index 1744162e6cec6..9c8867a17711e 100644 --- a/tests/ui/suggestions/multi-suggestion.ascii.stderr +++ b/tests/ui/suggestions/multi-suggestion.ascii.stderr @@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed(); LL - let _ = Box {}; LL + let _ = Box::new_in(_, _); | - = and 12 other candidates + = and 13 other candidates help: consider using the `Default` trait | LL - let _ = Box {}; diff --git a/tests/ui/suggestions/multi-suggestion.unicode.stderr b/tests/ui/suggestions/multi-suggestion.unicode.stderr index 4835c263f1901..4fdab51493e26 100644 --- a/tests/ui/suggestions/multi-suggestion.unicode.stderr +++ b/tests/ui/suggestions/multi-suggestion.unicode.stderr @@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed(); LL - let _ = Box {}; LL + let _ = Box::new_in(_, _); │ - ╰ and 12 other candidates + ╰ and 13 other candidates help: consider using the `Default` trait ╭╴ LL - let _ = Box {};