Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
37 changes: 16 additions & 21 deletions compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1957,10 +1957,13 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub crate_info: CrateInfo,
pub codegen_worker_receive: Receiver<CguMessage>,
pub shared_emitter_main: SharedEmitterMain,
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,
}

impl<B: ExtraBackendMethods> OngoingCodegen<B> {
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_data_structures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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 = [
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_lexer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
7 changes: 1 addition & 6 deletions compiler/rustc_target/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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
13 changes: 11 additions & 2 deletions library/std/src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
143 changes: 143 additions & 0 deletions tests/assembly-llvm/reg-struct-return.rs
Original file line number Diff line number Diff line change
@@ -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