mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 10:18:25 +00:00
Use captures(address) instead of captures(none) for indirect args
While provenance cannot be captured through these arguments, the address / object identity can.
This commit is contained in:
parent
ace9a74442
commit
c3ab409b4f
@ -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),
|
||||
@ -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));
|
||||
|
@ -263,7 +263,7 @@ pub(crate) enum AttributeKind {
|
||||
MinSize = 4,
|
||||
Naked = 5,
|
||||
NoAlias = 6,
|
||||
NoCapture = 7,
|
||||
CapturesAddress = 7,
|
||||
NoInline = 8,
|
||||
NonNull = 9,
|
||||
NoRedZone = 10,
|
||||
|
@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind {
|
||||
MinSize = 4,
|
||||
Naked = 5,
|
||||
NoAlias = 6,
|
||||
NoCapture = 7,
|
||||
CapturesAddress = 7,
|
||||
NoInline = 8,
|
||||
NonNull = 9,
|
||||
NoRedZone = 10,
|
||||
@ -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:
|
||||
@ -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");
|
||||
}
|
||||
@ -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(
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
@ -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();
|
||||
@ -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();
|
||||
@ -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();
|
||||
|
@ -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) {}
|
||||
|
||||
@ -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] }
|
||||
|
@ -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 }
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
@ -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(
|
||||
|
@ -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(
|
||||
@ -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(
|
||||
|
@ -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(
|
||||
@ -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(
|
||||
|
15
tests/ui/codegen/indirect-nocapture.rs
Normal file
15
tests/ui/codegen/indirect-nocapture.rs
Normal file
@ -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…
x
Reference in New Issue
Block a user