Auto merge of #145949 - jhpratt:rollup-smzd7tr, r=jhpratt
Rollup of 5 pull requests Successful merges: - rust-lang/rust#145382 (Add assembly test for `-Zreg-struct-return` option) - rust-lang/rust#145746 (Fix STD build failing for target_os = "espidf") - rust-lang/rust#145826 (Use AcceptContext in AttribueParser::check_target) - rust-lang/rust#145894 (Ensure the coordinator thread terminates before its channels drop) - rust-lang/rust#145946 (Remove unnecessary `[dependencies.unicode-properties]` entries.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
43a216604a
8 changed files with 179 additions and 47 deletions
|
|
@ -273,14 +273,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
(accept.accept_fn)(&mut cx, args);
|
||||
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
Self::check_type(accept.attribute_type, target, &mut cx);
|
||||
self.check_target(
|
||||
path.get_attribute_path(),
|
||||
attr.span,
|
||||
&accept.allowed_targets,
|
||||
target,
|
||||
target_id,
|
||||
&mut emit_lint,
|
||||
);
|
||||
Self::check_target(&accept.allowed_targets, target, &mut cx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use std::borrow::Cow;
|
|||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_feature::{AttributeType, Features};
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::{AttrPath, MethodKind, Target};
|
||||
use rustc_span::Span;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{MethodKind, Target};
|
||||
|
||||
use crate::AttributeParser;
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
|
|
@ -71,38 +70,34 @@ pub(crate) enum Policy {
|
|||
|
||||
impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
||||
pub(crate) fn check_target(
|
||||
&self,
|
||||
attr_name: AttrPath,
|
||||
attr_span: Span,
|
||||
allowed_targets: &AllowedTargets,
|
||||
target: Target,
|
||||
target_id: S::Id,
|
||||
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
|
||||
cx: &mut AcceptContext<'_, 'sess, S>,
|
||||
) {
|
||||
match allowed_targets.is_allowed(target) {
|
||||
AllowedResult::Allowed => {}
|
||||
AllowedResult::Warn => {
|
||||
let allowed_targets = allowed_targets.allowed_targets();
|
||||
let (applied, only) =
|
||||
allowed_targets_applied(allowed_targets, target, self.features);
|
||||
emit_lint(AttributeLint {
|
||||
id: target_id,
|
||||
span: attr_span,
|
||||
kind: AttributeLintKind::InvalidTarget {
|
||||
name: attr_name,
|
||||
let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
|
||||
let name = cx.attr_path.clone();
|
||||
let attr_span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
AttributeLintKind::InvalidTarget {
|
||||
name,
|
||||
target,
|
||||
only: if only { "only " } else { "" },
|
||||
applied,
|
||||
},
|
||||
});
|
||||
attr_span,
|
||||
);
|
||||
}
|
||||
AllowedResult::Error => {
|
||||
let allowed_targets = allowed_targets.allowed_targets();
|
||||
let (applied, only) =
|
||||
allowed_targets_applied(allowed_targets, target, self.features);
|
||||
self.dcx().emit_err(InvalidTarget {
|
||||
span: attr_span,
|
||||
name: attr_name,
|
||||
let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
|
||||
let name = cx.attr_path.clone();
|
||||
cx.dcx().emit_err(InvalidTarget {
|
||||
span: cx.attr_span.clone(),
|
||||
name,
|
||||
target: target.plural_name(),
|
||||
only: if only { "only " } else { "" },
|
||||
applied: DiagArgValue::StrListSepByAnd(
|
||||
|
|
|
|||
|
|
@ -1957,10 +1957,13 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
|
|||
pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
||||
pub backend: B,
|
||||
pub crate_info: CrateInfo,
|
||||
pub output_filenames: Arc<OutputFilenames>,
|
||||
// Field order below is intended to terminate the coordinator thread before two fields below
|
||||
// drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
|
||||
// `Drop` implementation for more info.
|
||||
pub coordinator: Coordinator<B>,
|
||||
pub codegen_worker_receive: Receiver<CguMessage>,
|
||||
pub shared_emitter_main: SharedEmitterMain,
|
||||
pub output_filenames: Arc<OutputFilenames>,
|
||||
pub coordinator: Coordinator<B>,
|
||||
}
|
||||
|
||||
impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ ena = "0.14.3"
|
|||
indexmap = "2.4.0"
|
||||
jobserver_crate = { version = "0.1.28", package = "jobserver" }
|
||||
measureme = "12.0.1"
|
||||
parking_lot = "0.12"
|
||||
rustc-hash = "2.0.0"
|
||||
rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
|
|
@ -34,9 +35,6 @@ version = "0.15.2"
|
|||
default-features = false
|
||||
features = ["nightly"] # for may_dangle
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.12"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.61.0"
|
||||
features = [
|
||||
|
|
|
|||
|
|
@ -15,12 +15,8 @@ Rust lexer used by rustc. No stability guarantees are provided.
|
|||
# Note that this crate purposefully does not depend on other rustc crates
|
||||
[dependencies]
|
||||
memchr.workspace = true
|
||||
unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] }
|
||||
unicode-xid = "0.2.0"
|
||||
|
||||
[dependencies.unicode-properties]
|
||||
version = "0.1.0"
|
||||
default-features = false
|
||||
features = ["emoji"]
|
||||
|
||||
[dev-dependencies]
|
||||
expect-test = "1.4.0"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ edition = "2024"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags.workspace = true
|
||||
object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] }
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_error_messages = { path = "../rustc_error_messages" }
|
||||
|
|
@ -20,9 +21,3 @@ serde_path_to_error = "0.1.17"
|
|||
tracing.workspace = true
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[dependencies.object]
|
||||
# tidy-alphabetical-start
|
||||
default-features = false
|
||||
features = ["elf", "macho"]
|
||||
version = "0.37.0"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -117,9 +117,18 @@ pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
|||
#[cfg(unix)]
|
||||
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
use crate::fs::OpenOptions;
|
||||
use crate::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
OpenOptions::new().custom_flags(libc::O_NOFOLLOW).open(path)?.set_permissions(perm)
|
||||
let mut options = OpenOptions::new();
|
||||
|
||||
// ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
|
||||
// Their filesystems do not have symbolic links, so no special handling is required.
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
|
||||
{
|
||||
use crate::os::unix::fs::OpenOptionsExt;
|
||||
options.custom_flags(libc::O_NOFOLLOW);
|
||||
}
|
||||
|
||||
options.open(path)?.set_permissions(perm)
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
|
|
|
|||
143
tests/assembly-llvm/reg-struct-return.rs
Normal file
143
tests/assembly-llvm/reg-struct-return.rs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
//! Tests that -Zreg-struct-return changes ABI for small struct returns
|
||||
//! from hidden-pointer convention to register-return on x86_32.
|
||||
//! This test covers:
|
||||
//! * Callee side, verifying that the structs are correctly loaded into registers when
|
||||
//! `-Zreg-struct-return` is activated
|
||||
//! * Caller side, verifying callers do receive returned structs in registers when
|
||||
//! `-Zreg-struct-return` is activated
|
||||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: -O --target=i686-unknown-linux-gnu -Crelocation-model=static
|
||||
//@ revisions: WITH WITHOUT
|
||||
//@[WITH] compile-flags: -Zreg-struct-return
|
||||
//@ needs-llvm-components: x86
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
// Verifies ABI changes for small structs, where both fields fit into one register.
|
||||
// WITH is expected to use register return, WITHOUT should use hidden pointer.
|
||||
mod Small {
|
||||
struct SmallStruct {
|
||||
a: i8,
|
||||
b: i8,
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
fn small() -> SmallStruct;
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn small_callee() -> SmallStruct {
|
||||
// (42 << 8) | 42 = 10794
|
||||
|
||||
// WITH-LABEL: small_callee
|
||||
// WITH: movw $10794, %ax
|
||||
// WITH: retl
|
||||
|
||||
// WITHOUT-LABEL: small_callee
|
||||
// WITHOUT: movl 4(%esp), %e{{.*}}
|
||||
// WITHOUT: movw $10794, (%e{{.*}})
|
||||
// WITHOUT: retl $4
|
||||
SmallStruct { a: 42, b: 42 }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn small_caller(dst: &mut SmallStruct) {
|
||||
// WITH-LABEL: small_caller
|
||||
// WITH: calll small
|
||||
// WITH: movw %ax, (%e{{.*}})
|
||||
|
||||
// WITHOUT-LABEL: small_caller
|
||||
// WITHOUT: calll small
|
||||
// WITHOUT: movzwl {{.*}}(%esp), %e[[TMP:..]]
|
||||
// WITHOUT: movw %[[TMP]], (%e{{..}})
|
||||
*dst = small();
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies ABI changes for a struct of size 8, which is the maximum size
|
||||
// for reg-struct-return.
|
||||
// WITH is expected to still use register return, WITHOUT should use hidden
|
||||
// pointer.
|
||||
mod Pivot {
|
||||
struct PivotStruct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
fn pivot() -> PivotStruct;
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pivot_callee() -> PivotStruct {
|
||||
// WITH-LABEL: pivot_callee
|
||||
// WITH: movl $42, %e{{.*}}
|
||||
// WITH: movl $42, %e{{.*}}
|
||||
// WITH: retl
|
||||
|
||||
// WITHOUT-LABEL: pivot_callee
|
||||
// WITHOUT: movl 4(%esp), %e{{.*}}
|
||||
// WITHOUT-DAG: movl $42, (%e{{.*}})
|
||||
// WITHOUT-DAG: movl $42, 4(%e{{.*}})
|
||||
// WITHOUT: retl $4
|
||||
PivotStruct { a: 42, b: 42 }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pivot_caller(dst: &mut PivotStruct) {
|
||||
// WITH-LABEL: pivot_caller
|
||||
// WITH: calll pivot
|
||||
// WITH-DAG: movl %e{{.*}}, 4(%e{{.*}})
|
||||
// WITH-DAG: movl %e{{.*}}, (%e{{.*}})
|
||||
|
||||
// WITHOUT-LABEL: pivot_caller
|
||||
// WITHOUT: calll pivot
|
||||
// WITHOUT: movsd {{.*}}(%esp), %[[TMP:xmm.]]
|
||||
// WITHOUT: movsd %[[TMP]], (%e{{..}})
|
||||
*dst = pivot();
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies ABI changes for a struct of size 12, which is larger than the
|
||||
// maximum size for reg-struct-return (8 bytes).
|
||||
// Here, the hidden pointer convention should be used even when `-Zreg-struct-return` is set.
|
||||
mod Large {
|
||||
struct LargeStruct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
fn large() -> LargeStruct;
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn large_callee() -> LargeStruct {
|
||||
// CHECK-LABEL: large_callee
|
||||
// CHECK: movl 4(%esp), %e{{.*}}
|
||||
// CHECK-DAG: movl $42, (%e{{.*}})
|
||||
// CHECK-DAG: movl $42, 4(%e{{.*}})
|
||||
// CHECK-DAG: movl $42, 8(%e{{.*}})
|
||||
// CHECK: retl $4
|
||||
LargeStruct { a: 42, b: 42, c: 42 }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn large_caller(dst: &mut LargeStruct) {
|
||||
// CHECK-LABEL: large_caller
|
||||
// CHECK: calll large
|
||||
// CHECK-DAG: movl {{.*}}(%esp), %[[TMP1:e..]]
|
||||
// CHECK-DAG: movl %[[TMP1]], {{.*}}(%e{{..}})
|
||||
// CHECK-DAG: movsd {{.*}}(%esp), %[[TMP2:xmm.]]
|
||||
// CHECK-DAG: movsd %[[TMP2]], {{.*}}(%e{{..}})
|
||||
*dst = large();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue