Auto merge of #132020 - workingjubilee:rollup-a8iehqg, r=workingjubilee

Rollup of 6 pull requests

Successful merges:

 - #130432 (rust_for_linux: -Zregparm=<N> commandline flag for X86 (#116972))
 - #131697 (`rt::Argument`: elide lifetimes)
 - #131807 (Always specify `llvm_abiname` for RISC-V targets)
 - #131954 (shave 150ms off bootstrap)
 - #132015 (Move const trait tests from `ui/rfcs/rfc-2632-const-trait-impl` to `ui/traits/const-traits`)
 - #132017 (Update triagebot.toml)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-22 05:49:18 +00:00
commit f225713007
281 changed files with 495 additions and 95 deletions

View File

@ -30,7 +30,7 @@ use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::FnAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
use crate::common::{SignType, TypeReflection, type_is_pointer};
use crate::context::CodegenCx;
@ -2347,6 +2347,12 @@ impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> {
}
}
impl<'tcx> HasX86AbiOpt for Builder<'_, '_, 'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
self.cx.x86_abi_opt()
}
}
pub trait ToGccComp {
fn to_gcc_comparison(&self) -> ComparisonOp;
}

View File

@ -19,7 +19,9 @@ use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi};
use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
};
use crate::callee::get_fn;
use crate::common::SignType;
@ -538,6 +540,12 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
}
}
impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
X86Abi { regparm: self.tcx.sess.opts.unstable_opts.regparm }
}
}
impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {

View File

@ -836,6 +836,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(profile_emit, Some(PathBuf::from("abc")));
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
tracked!(profiler_runtime, "abc".to_string());
tracked!(regparm, Some(3));
tracked!(relax_elf_relocations, Some(true));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
tracked!(sanitizer, SanitizerSet::ADDRESS);

View File

@ -21,7 +21,9 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call};
use rustc_target::spec::abi::Abi as SpecAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi};
use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, PanicStrategy, Target, WasmCAbi, X86Abi,
};
use tracing::debug;
use {rustc_abi as abi, rustc_hir as hir};
@ -544,6 +546,12 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
}
}
impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
X86Abi { regparm: self.sess.opts.unstable_opts.regparm }
}
}
impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
@ -595,6 +603,12 @@ impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> {
}
}
impl<'tcx> HasX86AbiOpt for LayoutCx<'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
self.calc.cx.x86_abi_opt()
}
}
impl<'tcx> HasTyCtxt<'tcx> for LayoutCx<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.calc.cx

View File

@ -136,3 +136,6 @@ session_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
session_unsupported_regparm = `-Zregparm={$regparm}` is unsupported (valid values 0-3)
session_unsupported_regparm_arch = `-Zregparm=N` is only supported on x86

View File

@ -485,6 +485,16 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664;
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
#[derive(Diagnostic)]
#[diag(session_unsupported_regparm)]
pub(crate) struct UnsupportedRegparm {
pub(crate) regparm: u32,
}
#[derive(Diagnostic)]
#[diag(session_unsupported_regparm_arch)]
pub(crate) struct UnsupportedRegparmArch;
#[derive(Diagnostic)]
#[diag(session_failed_to_create_profiler)]
pub(crate) struct FailedToCreateProfiler {

View File

@ -2000,6 +2000,11 @@ options! {
"enable queries of the dependency graph for regression testing (default: no)"),
randomize_layout: bool = (false, parse_bool, [TRACKED],
"randomize the layout of types (default: no)"),
regparm: Option<u32> = (None, parse_opt_number, [TRACKED],
"On x86-32 targets, setting this to N causes the compiler to pass N arguments \
in registers EAX, EDX, and ECX instead of on the stack for\
\"C\", \"cdecl\", and \"stdcall\" fn.\
It is UNSOUND to link together crates that use different values for this flag!"),
relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether ELF relocations can be relaxed"),
remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],

View File

@ -1337,6 +1337,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
}
if let Some(regparm) = sess.opts.unstable_opts.regparm {
if regparm > 3 {
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
}
if sess.target.arch != "x86" {
sess.dcx().emit_err(errors::UnsupportedRegparmArch);
}
}
// The code model check applies to `thunk` and `thunk-extern`, but not `thunk-inline`, so it is
// kept as a `match` to force a change if new ones are added, even if we currently only support
// `thunk-extern` like Clang.

View File

@ -6,7 +6,7 @@ use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
mod aarch64;
mod amdgpu;
@ -631,7 +631,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
) -> Result<(), AdjustForForeignAbiError>
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt,
{
if abi == spec::abi::Abi::X86Interrupt {
if let Some(arg) = self.args.first_mut() {
@ -643,14 +643,18 @@ impl<'a, Ty> FnAbi<'a, Ty> {
let spec = cx.target_spec();
match &spec.arch[..] {
"x86" => {
let flavor = if let spec::abi::Abi::Fastcall { .. }
| spec::abi::Abi::Vectorcall { .. } = abi
{
x86::Flavor::FastcallOrVectorcall
} else {
x86::Flavor::General
let (flavor, regparm) = match abi {
spec::abi::Abi::Fastcall { .. } | spec::abi::Abi::Vectorcall { .. } => {
(x86::Flavor::FastcallOrVectorcall, None)
}
spec::abi::Abi::C { .. }
| spec::abi::Abi::Cdecl { .. }
| spec::abi::Abi::Stdcall { .. } => {
(x86::Flavor::General, cx.x86_abi_opt().regparm)
}
_ => (x86::Flavor::General, None),
};
x86::compute_abi_info(cx, self, flavor);
x86::compute_abi_info(cx, self, x86::X86Options { flavor, regparm });
}
"x86_64" => match abi {
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),

View File

@ -8,7 +8,12 @@ pub(crate) enum Flavor {
FastcallOrVectorcall,
}
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
pub(crate) struct X86Options {
pub flavor: Flavor,
pub regparm: Option<u32>,
}
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec,
@ -128,58 +133,77 @@ where
}
}
if flavor == Flavor::FastcallOrVectorcall {
// Mark arguments as InReg like clang does it,
// so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
fill_inregs(cx, fn_abi, opts, false);
}
// Clang reference: lib/CodeGen/TargetInfo.cpp
// See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
pub(crate) fn fill_inregs<'a, Ty, C>(
cx: &C,
fn_abi: &mut FnAbi<'a, Ty>,
opts: X86Options,
rust_abi: bool,
) where
Ty: TyAbiInterface<'a, C> + Copy,
{
if opts.flavor != Flavor::FastcallOrVectorcall && opts.regparm.is_none_or(|x| x == 0) {
return;
}
// Mark arguments as InReg like clang does it,
// so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall.
// IsSoftFloatABI is only set to true on ARM platforms,
// which in turn can't be x86?
// Clang reference: lib/CodeGen/TargetInfo.cpp
// See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
let mut free_regs = 2;
// IsSoftFloatABI is only set to true on ARM platforms,
// which in turn can't be x86?
for arg in fn_abi.args.iter_mut() {
let attrs = match arg.mode {
PassMode::Ignore
| PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
continue;
}
PassMode::Direct(ref mut attrs) => attrs,
PassMode::Pair(..)
| PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ }
| PassMode::Cast { .. } => {
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
}
};
// 2 for fastcall/vectorcall, regparm limited by 3 otherwise
let mut free_regs = opts.regparm.unwrap_or(2).into();
// At this point we know this must be a primitive of sorts.
let unit = arg.layout.homogeneous_aggregate(cx).unwrap().unit().unwrap();
assert_eq!(unit.size, arg.layout.size);
if unit.kind == RegKind::Float {
// For types generating PassMode::Cast, InRegs will not be set.
// Maybe, this is a FIXME
let has_casts = fn_abi.args.iter().any(|arg| matches!(arg.mode, PassMode::Cast { .. }));
if has_casts && rust_abi {
return;
}
for arg in fn_abi.args.iter_mut() {
let attrs = match arg.mode {
PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
continue;
}
let size_in_regs = (arg.layout.size.bits() + 31) / 32;
if size_in_regs == 0 {
continue;
PassMode::Direct(ref mut attrs) => attrs,
PassMode::Pair(..)
| PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ }
| PassMode::Cast { .. } => {
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
}
};
if size_in_regs > free_regs {
break;
}
// At this point we know this must be a primitive of sorts.
let unit = arg.layout.homogeneous_aggregate(cx).unwrap().unit().unwrap();
assert_eq!(unit.size, arg.layout.size);
if matches!(unit.kind, RegKind::Float | RegKind::Vector) {
continue;
}
free_regs -= size_in_regs;
let size_in_regs = (arg.layout.size.bits() + 31) / 32;
if arg.layout.size.bits() <= 32 && unit.kind == RegKind::Integer {
attrs.set(ArgAttribute::InReg);
}
if size_in_regs == 0 {
continue;
}
if free_regs == 0 {
break;
}
if size_in_regs > free_regs {
break;
}
free_regs -= size_in_regs;
if arg.layout.size.bits() <= 32 && unit.kind == RegKind::Integer {
attrs.set(ArgAttribute::InReg);
}
if free_regs == 0 {
break;
}
}
}

View File

@ -2096,6 +2096,18 @@ pub trait HasWasmCAbiOpt {
fn wasm_c_abi_opt(&self) -> WasmCAbi;
}
/// x86 (32-bit) abi options.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct X86Abi {
/// On x86-32 targets, the regparm N causes the compiler to pass arguments
/// in registers EAX, EDX, and ECX instead of on the stack.
pub regparm: Option<u32>,
}
pub trait HasX86AbiOpt {
fn x86_abi_opt(&self) -> X86Abi;
}
type StaticCow<T> = Cow<'static, T>;
/// Optional aspects of a target specification.

View File

@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(32),
atomic_cas: false,
features: "+forced-atomics".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -29,6 +29,7 @@ pub(crate) fn target() -> Target {
atomic_cas: true,
features: "+m".into(),
llvm_abiname: "ilp32".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,

View File

@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(32),
atomic_cas: false,
features: "+m,+forced-atomics".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -19,6 +19,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -27,6 +27,7 @@ pub(crate) fn target() -> Target {
atomic_cas: true,
features: "+m,+a,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -19,6 +19,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -21,6 +21,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Unwind,
relocation_model: RelocModel::Static,
..Default::default()

View File

@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Unwind,
relocation_model: RelocModel::Static,
..Default::default()

View File

@ -30,6 +30,7 @@ pub(crate) fn target() -> Target {
atomic_cas: true,
features: "+m,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(32),
atomic_cas: false,
features: "+m,+c,+forced-atomics".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View File

@ -21,6 +21,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+c".into(),
llvm_abiname: "ilp32".into(),
panic_strategy: PanicStrategy::Unwind,
relocation_model: RelocModel::Static,
..Default::default()

View File

@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+c".into(),
llvm_abiname: "lp64".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View File

@ -24,6 +24,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+c".into(),
llvm_abiname: "lp64".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View File

@ -152,6 +152,17 @@ impl Target {
if self.crt_static_default || self.crt_static_allows_dylibs {
assert!(self.crt_static_respected);
}
// Check that RISC-V targets always specify which ABI they use.
match &*self.arch {
"riscv32" => {
assert_matches!(&*self.llvm_abiname, "ilp32" | "ilp32f" | "ilp32d" | "ilp32e")
}
"riscv64" => {
assert_matches!(&*self.llvm_abiname, "lp64" | "lp64f" | "lp64d" | "lp64q")
}
_ => {}
}
}
// Add your target to the whitelist if it has `std` library

View File

@ -94,11 +94,11 @@ pub struct Argument<'a> {
}
#[rustc_diagnostic_item = "ArgumentMethods"]
impl<'a> Argument<'a> {
impl Argument<'_> {
#[inline(always)]
fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
Argument {
// INVARIANT: this creates an `ArgumentType<'b>` from a `&'b T` and
// INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
// a `fn(&T, ...)`, so the invariant is maintained.
ty: ArgumentType::Placeholder {
value: NonNull::from(x).cast(),
@ -110,43 +110,43 @@ impl<'a> Argument<'a> {
}
#[inline(always)]
pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'b> {
pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
Self::new(x, Display::fmt)
}
#[inline(always)]
pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'b> {
pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
Self::new(x, Debug::fmt)
}
#[inline(always)]
pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'b> {
pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
Self::new(x, |_, _| Ok(()))
}
#[inline(always)]
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'b> {
pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
Self::new(x, Octal::fmt)
}
#[inline(always)]
pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'b> {
pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
Self::new(x, LowerHex::fmt)
}
#[inline(always)]
pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'b> {
pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
Self::new(x, UpperHex::fmt)
}
#[inline(always)]
pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'b> {
pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
Self::new(x, Pointer::fmt)
}
#[inline(always)]
pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'b> {
pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
Self::new(x, Binary::fmt)
}
#[inline(always)]
pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'b> {
pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
Self::new(x, LowerExp::fmt)
}
#[inline(always)]
pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'b> {
pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
Self::new(x, UpperExp::fmt)
}
#[inline(always)]

View File

@ -545,23 +545,28 @@ impl Build {
.args(["--get-regexp", "path"])
.run_capture(self)
.stdout();
for line in output.lines() {
std::thread::scope(|s| {
// Look for `submodule.$name.path = $path`
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
let submodule = line.split_once(' ').unwrap().1;
self.update_existing_submodule(submodule);
}
for line in output.lines() {
let submodule = line.split_once(' ').unwrap().1;
let config = self.config.clone();
s.spawn(move || {
Self::update_existing_submodule(&config, submodule);
});
}
});
}
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
pub fn update_existing_submodule(&self, submodule: &str) {
pub fn update_existing_submodule(config: &Config, submodule: &str) {
// Avoid running git when there isn't a git checkout.
if !self.config.submodules() {
if !config.submodules() {
return;
}
if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
self.config.update_submodule(submodule);
config.update_submodule(submodule);
}
}

View File

@ -10,7 +10,7 @@ use std::path::Path;
use super::helpers;
use crate::Build;
use crate::utils::helpers::{output, t};
use crate::utils::helpers::{start_process, t};
#[derive(Clone, Default)]
pub enum GitInfo {
@ -56,7 +56,7 @@ impl GitInfo {
}
// Ok, let's scrape some info
let ver_date = output(
let ver_date = start_process(
helpers::git(Some(dir))
.arg("log")
.arg("-1")
@ -65,14 +65,14 @@ impl GitInfo {
.as_command_mut(),
);
let ver_hash =
output(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
let short_ver_hash = output(
start_process(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
let short_ver_hash = start_process(
helpers::git(Some(dir)).arg("rev-parse").arg("--short=9").arg("HEAD").as_command_mut(),
);
GitInfo::Present(Some(Info {
commit_date: ver_date.trim().to_string(),
sha: ver_hash.trim().to_string(),
short_sha: short_ver_hash.trim().to_string(),
commit_date: ver_date().trim().to_string(),
sha: ver_hash().trim().to_string(),
short_sha: short_ver_hash().trim().to_string(),
}))
}

View File

@ -288,6 +288,33 @@ pub fn output(cmd: &mut Command) -> String {
String::from_utf8(output.stdout).unwrap()
}
/// Spawn a process and return a closure that will wait for the process
/// to finish and then return its output. This allows the spawned process
/// to do work without immediately blocking bootstrap.
#[track_caller]
pub fn start_process(cmd: &mut Command) -> impl FnOnce() -> String {
let child = match cmd.stderr(Stdio::inherit()).stdout(Stdio::piped()).spawn() {
Ok(child) => child,
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),
};
let command = format!("{:?}", cmd);
move || {
let output = child.wait_with_output().unwrap();
if !output.status.success() {
panic!(
"command did not execute successfully: {}\n\
expected success, got: {}",
command, output.status
);
}
String::from_utf8(output.stdout).unwrap()
}
}
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> SystemTime {
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)

View File

@ -0,0 +1,20 @@
# `regparm`
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/131749.
------------------------
Option -Zregparm=N causes the compiler to pass N arguments
in registers EAX, EDX, and ECX instead of on the stack for "C", "cdecl", and "stdcall" fn.
It is UNSOUND to link together crates that use different values for this flag.
It is only supported on `x86`.
It is equivalent to [Clang]'s and [GCC]'s `-mregparm`.
Supported values for this option are 0-3.
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mregparm
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-regparm-function-attribute_002c-x86
Implementation details:
For eligible arguments, llvm `inreg` attribute is set.

View File

@ -3720,16 +3720,6 @@ ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs
ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs
ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs
ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs
ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs
ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs
ui/rust-2018/issue-51008-1.rs
ui/rust-2018/issue-51008.rs
ui/rust-2018/issue-52202-use-suggestions.rs
@ -3983,6 +3973,16 @@ ui/traits/alias/issue-75983.rs
ui/traits/alias/issue-83613.rs
ui/traits/associated_type_bound/issue-51446.rs
ui/traits/auxiliary/issue_89119_intercrate_caching.rs
ui/traits/const-traits/issue-100222.rs
ui/traits/const-traits/issue-102156.rs
ui/traits/const-traits/issue-102985.rs
ui/traits/const-traits/issue-103677.rs
ui/traits/const-traits/issue-79450.rs
ui/traits/const-traits/issue-88155.rs
ui/traits/const-traits/issue-92111.rs
ui/traits/const-traits/issue-92230-wf-super-trait-env.rs
ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs
ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs
ui/traits/issue-103563.rs
ui/traits/issue-104322.rs
ui/traits/issue-105231.rs

View File

@ -0,0 +1,46 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target riscv64imac-unknown-none-elf -Ctarget-feature=+f,+d
//@ needs-llvm-components: riscv
#![feature(no_core, lang_items, f16)]
#![crate_type = "lib"]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for f16 {}
impl Copy for f32 {}
impl Copy for f64 {}
// This test checks that the floats are all returned in `a0` as required by the `lp64` ABI.
// CHECK-LABEL: read_f16
#[no_mangle]
pub extern "C" fn read_f16(x: &f16) -> f16 {
// CHECK: lh a0, 0(a0)
// CHECK-NEXT: lui a1, 1048560
// CHECK-NEXT: or a0, a0, a1
// CHECK-NEXT: ret
*x
}
// CHECK-LABEL: read_f32
#[no_mangle]
pub extern "C" fn read_f32(x: &f32) -> f32 {
// CHECK: flw fa5, 0(a0)
// CHECK-NEXT: fmv.x.w a0, fa5
// CHECK-NEXT: ret
*x
}
// CHECK-LABEL: read_f64
#[no_mangle]
pub extern "C" fn read_f64(x: &f64) -> f64 {
// CHECK: ld a0, 0(a0)
// CHECK-NEXT: ret
*x
}

View File

@ -0,0 +1,125 @@
// Checks how `regparm` flag works with different calling conventions:
// marks function arguments as "inreg" like the C/C++ compilers for the platforms.
// x86 only.
//@ compile-flags: --target i686-unknown-linux-gnu -O -C no-prepopulate-passes
//@ needs-llvm-components: x86
//@ revisions:regparm0 regparm1 regparm2 regparm3
//@[regparm0] compile-flags: -Zregparm=0
//@[regparm1] compile-flags: -Zregparm=1
//@[regparm2] compile-flags: -Zregparm=2
//@[regparm3] compile-flags: -Zregparm=3
#![crate_type = "lib"]
#![no_core]
#![feature(no_core, lang_items, repr_simd)]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
pub mod tests {
// regparm doesn't work for "fastcall" calling conv (only 2 inregs)
// CHECK: @f1(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
// regparm0: @f3(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm1: @f3(i32 inreg noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm2: @f3(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
// regparm3: @f3(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3)
#[no_mangle]
pub extern "C" fn f3(_: i32, _: i32, _: i32) {}
// regparm0: @f4(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm1: @f4(i32 inreg noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm2: @f4(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
// regparm3: @f4(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3)
#[no_mangle]
pub extern "cdecl" fn f4(_: i32, _: i32, _: i32) {}
// regparm0: @f5(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm1: @f5(i32 inreg noundef %_1, i32 noundef %_2, i32 noundef %_3)
// regparm2: @f5(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
// regparm3: @f5(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3)
#[no_mangle]
pub extern "stdcall" fn f5(_: i32, _: i32, _: i32) {}
// regparm doesn't work for thiscall
// CHECK: @f6(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "thiscall" fn f6(_: i32, _: i32, _: i32) {}
struct S1 {
x1: i32,
}
// regparm0: @f7(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3, i32 noundef %_4)
// regparm1: @f7(i32 inreg noundef %_1, i32 noundef %_2, i32 noundef %_3, i32 noundef %_4)
// regparm2: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3, i32 noundef %_4)
// regparm3: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3,
// regparm3-SAME: i32 noundef %_4)
#[no_mangle]
pub extern "C" fn f7(_: i32, _: i32, _: S1, _: i32) {}
#[repr(C)]
struct S2 {
x1: i32,
x2: i32,
}
// regparm0: @f8(i32 noundef %_1, i32 noundef %_2, ptr {{.*}} %_3, i32 noundef %_4)
// regparm1: @f8(i32 inreg noundef %_1, i32 noundef %_2, ptr {{.*}} %_3, i32 noundef %_4)
// regparm2: @f8(i32 inreg noundef %_1, i32 inreg noundef %_2, ptr {{.*}} %_3, i32 noundef %_4)
// regparm3: @f8(i32 inreg noundef %_1, i32 inreg noundef %_2, ptr {{.*}} %_3,
// regparm3-SAME: i32 inreg noundef %_4)
#[no_mangle]
pub extern "C" fn f8(_: i32, _: i32, _: S2, _: i32) {}
// regparm0: @f9(i1 noundef zeroext %_1, i16 noundef signext %_2, i64 noundef %_3,
// regparm0-SAME: i128 noundef %_4)
// regparm1: @f9(i1 inreg noundef zeroext %_1, i16 noundef signext %_2, i64 noundef %_3,
// regparm1-SAME: i128 noundef %_4)
// regparm2: @f9(i1 inreg noundef zeroext %_1, i16 inreg noundef signext %_2, i64 noundef %_3,
// regparm2-SAME: i128 noundef %_4)
// regparm3: @f9(i1 inreg noundef zeroext %_1, i16 inreg noundef signext %_2, i64 noundef %_3,
// regparm3-SAME: i128 noundef %_4)
#[no_mangle]
pub extern "C" fn f9(_: bool, _: i16, _: i64, _: u128) {}
// regparm0: @f10(float noundef %_1, double noundef %_2, i1 noundef zeroext %_3,
// regparm0-SAME: i16 noundef signext %_4)
// regparm1: @f10(float noundef %_1, double noundef %_2, i1 inreg noundef zeroext %_3,
// regparm1-SAME: i16 noundef signext %_4)
// regparm2: @f10(float noundef %_1, double noundef %_2, i1 inreg noundef zeroext %_3,
// regparm2-SAME: i16 inreg noundef signext %_4)
// regparm3: @f10(float noundef %_1, double noundef %_2, i1 inreg noundef zeroext %_3,
// regparm3-SAME: i16 inreg noundef signext %_4)
#[no_mangle]
pub extern "C" fn f10(_: f32, _: f64, _: bool, _: i16) {}
#[allow(non_camel_case_types)]
#[repr(simd)]
pub struct __m128([f32; 4]);
// regparm0: @f11(i32 noundef %_1, <4 x float> %_2, i32 noundef %_3, i32 noundef %_4)
// regparm1: @f11(i32 inreg noundef %_1, <4 x float> %_2, i32 noundef %_3, i32 noundef %_4)
// regparm2: @f11(i32 inreg noundef %_1, <4 x float> %_2, i32 inreg noundef %_3,
// regparm2-SAME: i32 noundef %_4)
// regparm3: @f11(i32 inreg noundef %_1, <4 x float> %_2, i32 inreg noundef %_3,
// regparm3-SAME: i32 inreg noundef %_4)
#[no_mangle]
pub extern "C" fn f11(_: i32, _: __m128, _: i32, _: i32) {}
#[allow(non_camel_case_types)]
#[repr(simd)]
pub struct __m256([f32; 8]);
// regparm0: @f12(i32 noundef %_1, <8 x float> %_2, i32 noundef %_3, i32 noundef %_4)
// regparm1: @f12(i32 inreg noundef %_1, <8 x float> %_2, i32 noundef %_3, i32 noundef %_4)
// regparm2: @f12(i32 inreg noundef %_1, <8 x float> %_2, i32 inreg noundef %_3,
// regparm2-SAME: i32 noundef %_4)
// regparm3: @f12(i32 inreg noundef %_1, <8 x float> %_2, i32 inreg noundef %_3,
// regparm3-SAME: i32 inreg noundef %_4)
#[no_mangle]
pub extern "C" fn f12(_: i32, _: __m256, _: i32, _: i32) {}
}

View File

@ -10,7 +10,7 @@
//@[riscv32imac] compile-flags: --target=riscv32imac-unknown-none-elf
//@[riscv32imac] needs-llvm-components: riscv
// riscv32imac-NOT: !"target-abi"
// riscv32imac: !{i32 1, !"target-abi", !"ilp32"}
#![feature(no_core, lang_items)]
#![crate_type = "lib"]

View File

@ -17,7 +17,7 @@ LL | println!("{:?}", foo);
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Foo`
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'a>::new_debug`
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'_>::new_debug`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -25,7 +25,7 @@ LL | println!("{:?}", take_array_from_mut(&mut arr, i));
= note: required for `[i32; _]` to implement `Debug`
= note: 1 redundant requirement hidden
= note: required for `&mut [i32; _]` to implement `Debug`
note: required by a bound in `core::fmt::rt::Argument::<'a>::new_debug`
note: required by a bound in `core::fmt::rt::Argument::<'_>::new_debug`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
help: consider specifying the generic arguments
|

View File

@ -17,7 +17,7 @@ LL | format!("{:X}", "3");
i32
and 9 others
= note: required for `&str` to implement `UpperHex`
note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex`
note: required by a bound in `core::fmt::rt::Argument::<'_>::new_upper_hex`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -0,0 +1,4 @@
error: `-Zregparm=4` is unsupported (valid values 0-3)
error: aborting due to 1 previous error

View File

@ -0,0 +1,24 @@
//@ revisions: regparm0 regparm1 regparm2 regparm3 regparm4
//@ needs-llvm-components: x86
//@ compile-flags: --target i686-unknown-linux-gnu
//@[regparm0] check-pass
//@[regparm0] compile-flags: -Zregparm=0
//@[regparm1] check-pass
//@[regparm1] compile-flags: -Zregparm=1
//@[regparm2] check-pass
//@[regparm2] compile-flags: -Zregparm=2
//@[regparm3] check-pass
//@[regparm3] compile-flags: -Zregparm=3
//@[regparm4] check-fail
//@[regparm4] compile-flags: -Zregparm=4
//@[regparm4] error-pattern: `-Zregparm=4` is unsupported (valid values 0-3)
#![feature(no_core)]
#![no_core]
#![no_main]

View File

@ -0,0 +1,4 @@
error: `-Zregparm=N` is only supported on x86
error: aborting due to 1 previous error

View File

@ -0,0 +1,21 @@
//@ revisions: x86 x86_64 aarch64
//@ compile-flags: -Zregparm=3
//@[x86] check-pass
//@[x86] needs-llvm-components: x86
//@[x86] compile-flags: --target i686-unknown-linux-gnu
//@[x86_64] check-fail
//@[x86_64] needs-llvm-components: x86
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86_64] error-pattern: `-Zregparm=N` is only supported on x86
//@[aarch64] check-fail
//@[aarch64] needs-llvm-components: aarch64
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//@[aarch64] error-pattern: `-Zregparm=N` is only supported on x86
#![feature(no_core)]
#![no_core]
#![no_main]

View File

@ -0,0 +1,4 @@
error: `-Zregparm=N` is only supported on x86
error: aborting due to 1 previous error

Some files were not shown because too many files have changed in this diff Show More