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
8 changes: 5 additions & 3 deletions compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =

const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [
(ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
(ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture),
(ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
(ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
(ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
(ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
Expand Down Expand Up @@ -84,8 +84,10 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
}
for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
if regular.contains(attr) {
// captures(address, read_provenance) is only available since LLVM 21.
if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) {
// captures(...) is only available since LLVM 21.
if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress)
&& llvm_util::get_version() < (21, 0, 0)
{
continue;
}
attrs.push(llattr.create_attr(cx.llcx));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ pub(crate) enum AttributeKind {
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
Expand Down
15 changes: 5 additions & 10 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind {
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
Expand Down Expand Up @@ -297,12 +297,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
return Attribute::Naked;
case LLVMRustAttributeKind::NoAlias:
return Attribute::NoAlias;
case LLVMRustAttributeKind::NoCapture:
#if LLVM_VERSION_GE(21, 0)
report_fatal_error("NoCapture doesn't exist in LLVM 21");
#else
return Attribute::NoCapture;
#endif
case LLVMRustAttributeKind::NoCfCheck:
return Attribute::NoCfCheck;
case LLVMRustAttributeKind::NoInline:
Expand Down Expand Up @@ -377,6 +371,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
#else
report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later");
#endif
case LLVMRustAttributeKind::CapturesAddress:
case LLVMRustAttributeKind::CapturesReadOnly:
report_fatal_error("Should be handled separately");
}
Expand Down Expand Up @@ -429,9 +424,9 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
extern "C" LLVMAttributeRef
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
#if LLVM_VERSION_GE(21, 0)
// LLVM 21 replaced the NoCapture attribute with Captures(none).
if (RustAttr == LLVMRustAttributeKind::NoCapture) {
return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
if (RustAttr == LLVMRustAttributeKind::CapturesAddress) {
return wrap(Attribute::getWithCaptureInfo(
*unwrap(C), CaptureInfo(CaptureComponents::Address)));
}
if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) {
return wrap(Attribute::getWithCaptureInfo(
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_target/src/callconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ mod attr_impl {
bitflags::bitflags! {
impl ArgAttribute: u8 {
const NoAlias = 1 << 1;
const NoCapture = 1 << 2;
const CapturesAddress = 1 << 2;
const NonNull = 1 << 3;
const ReadOnly = 1 << 4;
const InReg = 1 << 5;
Expand Down Expand Up @@ -400,11 +400,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
let mut attrs = ArgAttributes::new();

// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
// the value on the stack, so there are no aliases. The function
// can capture the address of the argument, but not the provenance.
attrs
.set(ArgAttribute::NoAlias)
.set(ArgAttribute::NoCapture)
.set(ArgAttribute::CapturesAddress)
.set(ArgAttribute::NonNull)
.set(ArgAttribute::NoUndef);
attrs.pointee_size = layout.size;
Expand Down
6 changes: 3 additions & 3 deletions tests/codegen-llvm/addr-of-mutate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
// See <https://github.com/rust-lang/rust/issues/111502>.

// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x)
// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x)
#[no_mangle]
pub fn foo(x: [u8; 128]) -> u8 {
let ptr = core::ptr::addr_of!(x).cast_mut();
Expand All @@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 {
x[0]
}

// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
Expand All @@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
}

// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen-llvm/function-arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
#[no_mangle]
pub fn notunpin_borrow(_: &NotUnpin) {}

// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1)
// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias noundef readonly align 4{{( captures\(address\))?}} dereferenceable(32) %_1)
#[no_mangle]
pub fn indirect_struct(_: S) {}

Expand Down Expand Up @@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
x
}

// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(address\))?}} dereferenceable(32){{( %_0)?}})
#[no_mangle]
pub fn struct_return() -> S {
S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,11 @@ pub struct IntDoubleInt {
c: i32,
}

// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a)
// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias noundef align 8{{( captures\(address\))?}} dereferenceable(24) %a)
#[no_mangle]
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}

// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0)
// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(address\))?}} dereferenceable(24) %_0)
#[no_mangle]
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
IntDoubleInt { a: 1, b: 2., c: 3 }
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/abi/c-zst.powerpc-linux.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/abi/c-zst.s390x-linux.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/abi/c-zst.sparc64-linux.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/abi/debug.generic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
Expand Down Expand Up @@ -527,7 +527,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/abi/debug.loongarch64.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
Expand Down Expand Up @@ -527,7 +527,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/abi/debug.riscv64.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
Expand Down Expand Up @@ -527,7 +527,7 @@ error: ABIs are not compatible
},
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/codegen/indirect-nocapture.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Regression test for issue #137668 where an indirect argument have been marked as nocapture
// despite the fact that callee did in fact capture the address.
//
//@ run-pass
//@ compile-flags: -Copt-level=2

#[inline(never)]
pub fn f(a: [u32; 64], b: [u32; 64]) -> bool {
&a as *const _ as usize != &b as *const _ as usize
}

fn main() {
static S: [u32; 64] = [0; 64];
assert!(f(S, S));
}
Loading