Skip to content

Commit d36f964

Browse files
committed
Auto merge of #145877 - nikic:capture-address, r=tmiasko
Use captures(address) instead of captures(none) for indirect args While provenance cannot be captured through these arguments, the address / object identity can. Fixes #137668. r? `@ghost`
2 parents cdb45c8 + c3ab409 commit d36f964

File tree

15 files changed

+47
-35
lines changed

15 files changed

+47
-35
lines changed

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
4444

4545
const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [
4646
(ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
47-
(ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture),
47+
(ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
4848
(ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
4949
(ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
5050
(ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
@@ -84,8 +84,10 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
8484
}
8585
for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
8686
if regular.contains(attr) {
87-
// captures(address, read_provenance) is only available since LLVM 21.
88-
if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) {
87+
// captures(...) is only available since LLVM 21.
88+
if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress)
89+
&& llvm_util::get_version() < (21, 0, 0)
90+
{
8991
continue;
9092
}
9193
attrs.push(llattr.create_attr(cx.llcx));

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ pub(crate) enum AttributeKind {
263263
MinSize = 4,
264264
Naked = 5,
265265
NoAlias = 6,
266-
NoCapture = 7,
266+
CapturesAddress = 7,
267267
NoInline = 8,
268268
NonNull = 9,
269269
NoRedZone = 10,

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind {
242242
MinSize = 4,
243243
Naked = 5,
244244
NoAlias = 6,
245-
NoCapture = 7,
245+
CapturesAddress = 7,
246246
NoInline = 8,
247247
NonNull = 9,
248248
NoRedZone = 10,
@@ -297,12 +297,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
297297
return Attribute::Naked;
298298
case LLVMRustAttributeKind::NoAlias:
299299
return Attribute::NoAlias;
300-
case LLVMRustAttributeKind::NoCapture:
301-
#if LLVM_VERSION_GE(21, 0)
302-
report_fatal_error("NoCapture doesn't exist in LLVM 21");
303-
#else
304-
return Attribute::NoCapture;
305-
#endif
306300
case LLVMRustAttributeKind::NoCfCheck:
307301
return Attribute::NoCfCheck;
308302
case LLVMRustAttributeKind::NoInline:
@@ -377,6 +371,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
377371
#else
378372
report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later");
379373
#endif
374+
case LLVMRustAttributeKind::CapturesAddress:
380375
case LLVMRustAttributeKind::CapturesReadOnly:
381376
report_fatal_error("Should be handled separately");
382377
}
@@ -429,9 +424,9 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
429424
extern "C" LLVMAttributeRef
430425
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
431426
#if LLVM_VERSION_GE(21, 0)
432-
// LLVM 21 replaced the NoCapture attribute with Captures(none).
433-
if (RustAttr == LLVMRustAttributeKind::NoCapture) {
434-
return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
427+
if (RustAttr == LLVMRustAttributeKind::CapturesAddress) {
428+
return wrap(Attribute::getWithCaptureInfo(
429+
*unwrap(C), CaptureInfo(CaptureComponents::Address)));
435430
}
436431
if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) {
437432
return wrap(Attribute::getWithCaptureInfo(

compiler/rustc_target/src/callconv/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ mod attr_impl {
114114
bitflags::bitflags! {
115115
impl ArgAttribute: u8 {
116116
const NoAlias = 1 << 1;
117-
const NoCapture = 1 << 2;
117+
const CapturesAddress = 1 << 2;
118118
const NonNull = 1 << 3;
119119
const ReadOnly = 1 << 4;
120120
const InReg = 1 << 5;
@@ -400,11 +400,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
400400
let mut attrs = ArgAttributes::new();
401401

402402
// For non-immediate arguments the callee gets its own copy of
403-
// the value on the stack, so there are no aliases. It's also
404-
// program-invisible so can't possibly capture
403+
// the value on the stack, so there are no aliases. The function
404+
// can capture the address of the argument, but not the provenance.
405405
attrs
406406
.set(ArgAttribute::NoAlias)
407-
.set(ArgAttribute::NoCapture)
407+
.set(ArgAttribute::CapturesAddress)
408408
.set(ArgAttribute::NonNull)
409409
.set(ArgAttribute::NoUndef);
410410
attrs.pointee_size = layout.size;

tests/codegen-llvm/addr-of-mutate.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
66
// See <https://github.com/rust-lang/rust/issues/111502>.
77

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

18-
// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
18+
// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
1919
#[no_mangle]
2020
pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
2121
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 {
2424
}
2525

2626
// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
27-
// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
27+
// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
2828
#[no_mangle]
2929
pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
3030
let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();

tests/codegen-llvm/function-arguments.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
134134
#[no_mangle]
135135
pub fn notunpin_borrow(_: &NotUnpin) {}
136136

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

@@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
197197
x
198198
}
199199

200-
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
200+
// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(address\))?}} dereferenceable(32){{( %_0)?}})
201201
#[no_mangle]
202202
pub fn struct_return() -> S {
203203
S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }

tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,11 @@ pub struct IntDoubleInt {
256256
c: i32,
257257
}
258258

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

263-
// 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)
263+
// 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)
264264
#[no_mangle]
265265
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
266266
IntDoubleInt { a: 1, b: 2., c: 3 }

tests/ui/abi/c-zst.powerpc-linux.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
2727
},
2828
mode: Indirect {
2929
attrs: ArgAttributes {
30-
regular: NoAlias | NoCapture | NonNull | NoUndef,
30+
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
3131
arg_ext: None,
3232
pointee_size: Size(0 bytes),
3333
pointee_align: Some(

tests/ui/abi/c-zst.s390x-linux.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
2727
},
2828
mode: Indirect {
2929
attrs: ArgAttributes {
30-
regular: NoAlias | NoCapture | NonNull | NoUndef,
30+
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
3131
arg_ext: None,
3232
pointee_size: Size(0 bytes),
3333
pointee_align: Some(

tests/ui/abi/c-zst.sparc64-linux.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
2727
},
2828
mode: Indirect {
2929
attrs: ArgAttributes {
30-
regular: NoAlias | NoCapture | NonNull | NoUndef,
30+
regular: NoAlias | CapturesAddress | NonNull | NoUndef,
3131
arg_ext: None,
3232
pointee_size: Size(0 bytes),
3333
pointee_align: Some(

0 commit comments

Comments
 (0)