Skip to content

Commit 46994aa

Browse files
authored
Merge pull request rust-lang#4279 from rust-lang/rustup-2025-04-18
Automatic Rustup
2 parents 765d4b2 + dc21c77 commit 46994aa

File tree

131 files changed

+1118
-477
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+1118
-477
lines changed

Cargo.lock

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,9 +2022,9 @@ checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7"
20222022

20232023
[[package]]
20242024
name = "libc"
2025-
version = "0.2.171"
2025+
version = "0.2.172"
20262026
source = "registry+https://github.com/rust-lang/crates.io-index"
2027-
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
2027+
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
20282028

20292029
[[package]]
20302030
name = "libdbus-sys"
@@ -2572,16 +2572,6 @@ version = "0.2.0"
25722572
source = "registry+https://github.com/rust-lang/crates.io-index"
25732573
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
25742574

2575-
[[package]]
2576-
name = "os_pipe"
2577-
version = "1.2.1"
2578-
source = "registry+https://github.com/rust-lang/crates.io-index"
2579-
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
2580-
dependencies = [
2581-
"libc",
2582-
"windows-sys 0.59.0",
2583-
]
2584-
25852575
[[package]]
25862576
name = "overload"
25872577
version = "0.1.1"
@@ -3142,7 +3132,6 @@ dependencies = [
31423132
"gimli 0.31.1",
31433133
"libc",
31443134
"object 0.36.7",
3145-
"os_pipe",
31463135
"regex",
31473136
"serde_json",
31483137
"similar",
@@ -3199,14 +3188,12 @@ dependencies = [
31993188

32003189
[[package]]
32013190
name = "rustc-rayon-core"
3202-
version = "0.5.0"
3191+
version = "0.5.1"
32033192
source = "registry+https://github.com/rust-lang/crates.io-index"
3204-
checksum = "67668daaf00e359c126f6dcb40d652d89b458a008c8afa727a42a2d20fca0b7f"
3193+
checksum = "2f42932dcd3bcbe484b38a3ccf79b7906fac41c02d408b5b1bac26da3416efdb"
32053194
dependencies = [
3206-
"crossbeam-channel",
32073195
"crossbeam-deque",
32083196
"crossbeam-utils",
3209-
"num_cpus",
32103197
]
32113198

32123199
[[package]]

compiler/rustc_ast/src/expand/autodiff_attrs.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,32 @@ pub enum DiffActivity {
5050
/// with it.
5151
Dual,
5252
/// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
53+
/// with it. It expects the shadow argument to be `width` times larger than the original
54+
/// input/output.
55+
Dualv,
56+
/// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
5357
/// with it. Drop the code which updates the original input/output for maximum performance.
5458
DualOnly,
59+
/// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
60+
/// with it. Drop the code which updates the original input/output for maximum performance.
61+
/// It expects the shadow argument to be `width` times larger than the original input/output.
62+
DualvOnly,
5563
/// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument.
5664
Duplicated,
5765
/// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument.
5866
/// Drop the code which updates the original input for maximum performance.
5967
DuplicatedOnly,
6068
/// All Integers must be Const, but these are used to mark the integer which represents the
6169
/// length of a slice/vec. This is used for safety checks on slices.
62-
FakeActivitySize,
70+
/// The integer (if given) specifies the size of the slice element in bytes.
71+
FakeActivitySize(Option<u32>),
72+
}
73+
74+
impl DiffActivity {
75+
pub fn is_dual_or_const(&self) -> bool {
76+
use DiffActivity::*;
77+
matches!(self, |Dual| DualOnly | Dualv | DualvOnly | Const)
78+
}
6379
}
6480
/// We generate one of these structs for each `#[autodiff(...)]` attribute.
6581
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
@@ -131,11 +147,7 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
131147
match mode {
132148
DiffMode::Error => false,
133149
DiffMode::Source => false,
134-
DiffMode::Forward => {
135-
activity == DiffActivity::Dual
136-
|| activity == DiffActivity::DualOnly
137-
|| activity == DiffActivity::Const
138-
}
150+
DiffMode::Forward => activity.is_dual_or_const(),
139151
DiffMode::Reverse => {
140152
activity == DiffActivity::Const
141153
|| activity == DiffActivity::Active
@@ -153,10 +165,8 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
153165
pub fn valid_ty_for_activity(ty: &P<Ty>, activity: DiffActivity) -> bool {
154166
use DiffActivity::*;
155167
// It's always allowed to mark something as Const, since we won't compute derivatives wrt. it.
156-
if matches!(activity, Const) {
157-
return true;
158-
}
159-
if matches!(activity, Dual | DualOnly) {
168+
// Dual variants also support all types.
169+
if activity.is_dual_or_const() {
160170
return true;
161171
}
162172
// FIXME(ZuseZ4) We should make this more robust to also
@@ -172,9 +182,7 @@ pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool {
172182
return match mode {
173183
DiffMode::Error => false,
174184
DiffMode::Source => false,
175-
DiffMode::Forward => {
176-
matches!(activity, Dual | DualOnly | Const)
177-
}
185+
DiffMode::Forward => activity.is_dual_or_const(),
178186
DiffMode::Reverse => {
179187
matches!(activity, Active | ActiveOnly | Duplicated | DuplicatedOnly | Const)
180188
}
@@ -189,10 +197,12 @@ impl Display for DiffActivity {
189197
DiffActivity::Active => write!(f, "Active"),
190198
DiffActivity::ActiveOnly => write!(f, "ActiveOnly"),
191199
DiffActivity::Dual => write!(f, "Dual"),
200+
DiffActivity::Dualv => write!(f, "Dualv"),
192201
DiffActivity::DualOnly => write!(f, "DualOnly"),
202+
DiffActivity::DualvOnly => write!(f, "DualvOnly"),
193203
DiffActivity::Duplicated => write!(f, "Duplicated"),
194204
DiffActivity::DuplicatedOnly => write!(f, "DuplicatedOnly"),
195-
DiffActivity::FakeActivitySize => write!(f, "FakeActivitySize"),
205+
DiffActivity::FakeActivitySize(s) => write!(f, "FakeActivitySize({:?})", s),
196206
}
197207
}
198208
}
@@ -220,7 +230,9 @@ impl FromStr for DiffActivity {
220230
"ActiveOnly" => Ok(DiffActivity::ActiveOnly),
221231
"Const" => Ok(DiffActivity::Const),
222232
"Dual" => Ok(DiffActivity::Dual),
233+
"Dualv" => Ok(DiffActivity::Dualv),
223234
"DualOnly" => Ok(DiffActivity::DualOnly),
235+
"DualvOnly" => Ok(DiffActivity::DualvOnly),
224236
"Duplicated" => Ok(DiffActivity::Duplicated),
225237
"DuplicatedOnly" => Ok(DiffActivity::DuplicatedOnly),
226238
_ => Err(()),

compiler/rustc_builtin_macros/src/autodiff.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -799,8 +799,19 @@ mod llvm_enzyme {
799799
d_inputs.push(shadow_arg.clone());
800800
}
801801
}
802-
DiffActivity::Dual | DiffActivity::DualOnly => {
803-
for i in 0..x.width {
802+
DiffActivity::Dual
803+
| DiffActivity::DualOnly
804+
| DiffActivity::Dualv
805+
| DiffActivity::DualvOnly => {
806+
// the *v variants get lowered to enzyme_dupv and enzyme_dupnoneedv, which cause
807+
// Enzyme to not expect N arguments, but one argument (which is instead larger).
808+
let iterations =
809+
if matches!(activity, DiffActivity::Dualv | DiffActivity::DualvOnly) {
810+
1
811+
} else {
812+
x.width
813+
};
814+
for i in 0..iterations {
804815
let mut shadow_arg = arg.clone();
805816
let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind {
806817
ident.name
@@ -823,7 +834,7 @@ mod llvm_enzyme {
823834
DiffActivity::Const => {
824835
// Nothing to do here.
825836
}
826-
DiffActivity::None | DiffActivity::FakeActivitySize => {
837+
DiffActivity::None | DiffActivity::FakeActivitySize(_) => {
827838
panic!("Should not happen");
828839
}
829840
}
@@ -887,8 +898,8 @@ mod llvm_enzyme {
887898
}
888899
};
889900

890-
if let DiffActivity::Dual = x.ret_activity {
891-
let kind = if x.width == 1 {
901+
if matches!(x.ret_activity, DiffActivity::Dual | DiffActivity::Dualv) {
902+
let kind = if x.width == 1 || matches!(x.ret_activity, DiffActivity::Dualv) {
892903
// Dual can only be used for f32/f64 ret.
893904
// In that case we return now a tuple with two floats.
894905
TyKind::Tup(thin_vec![ty.clone(), ty.clone()])
@@ -903,7 +914,7 @@ mod llvm_enzyme {
903914
let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
904915
d_decl.output = FnRetTy::Ty(ty);
905916
}
906-
if let DiffActivity::DualOnly = x.ret_activity {
917+
if matches!(x.ret_activity, DiffActivity::DualOnly | DiffActivity::DualvOnly) {
907918
// No need to change the return type,
908919
// we will just return the shadow in place of the primal return.
909920
// However, if we have a width > 1, then we don't return -> T, but -> [T; width]

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
123123
/// Empty string, to be used where LLVM expects an instruction name, indicating
124124
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
125125
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
126-
const UNNAMED: *const c_char = c"".as_ptr();
126+
pub(crate) const UNNAMED: *const c_char = c"".as_ptr();
127127

128128
impl<'ll, CX: Borrow<SCx<'ll>>> BackendTypes for GenericBuilder<'_, 'll, CX> {
129129
type Value = <GenericCx<'ll, CX> as BackendTypes>::Value;

compiler/rustc_codegen_llvm/src/builder/autodiff.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_middle::bug;
1010
use tracing::{debug, trace};
1111

1212
use crate::back::write::llvm_err;
13-
use crate::builder::SBuilder;
13+
use crate::builder::{SBuilder, UNNAMED};
1414
use crate::context::SimpleCx;
1515
use crate::declare::declare_simple_fn;
1616
use crate::errors::{AutoDiffWithoutEnable, LlvmError};
@@ -51,6 +51,7 @@ fn has_sret(fnc: &Value) -> bool {
5151
// using iterators and peek()?
5252
fn match_args_from_caller_to_enzyme<'ll>(
5353
cx: &SimpleCx<'ll>,
54+
builder: &SBuilder<'ll, 'll>,
5455
width: u32,
5556
args: &mut Vec<&'ll llvm::Value>,
5657
inputs: &[DiffActivity],
@@ -78,7 +79,9 @@ fn match_args_from_caller_to_enzyme<'ll>(
7879
let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
7980
let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
8081
let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
82+
let enzyme_dupv = cx.create_metadata("enzyme_dupv".to_string()).unwrap();
8183
let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
84+
let enzyme_dupnoneedv = cx.create_metadata("enzyme_dupnoneedv".to_string()).unwrap();
8285

8386
while activity_pos < inputs.len() {
8487
let diff_activity = inputs[activity_pos as usize];
@@ -90,13 +93,34 @@ fn match_args_from_caller_to_enzyme<'ll>(
9093
DiffActivity::Active => (enzyme_out, false),
9194
DiffActivity::ActiveOnly => (enzyme_out, false),
9295
DiffActivity::Dual => (enzyme_dup, true),
96+
DiffActivity::Dualv => (enzyme_dupv, true),
9397
DiffActivity::DualOnly => (enzyme_dupnoneed, true),
98+
DiffActivity::DualvOnly => (enzyme_dupnoneedv, true),
9499
DiffActivity::Duplicated => (enzyme_dup, true),
95100
DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true),
96-
DiffActivity::FakeActivitySize => (enzyme_const, false),
101+
DiffActivity::FakeActivitySize(_) => (enzyme_const, false),
97102
};
98103
let outer_arg = outer_args[outer_pos];
99104
args.push(cx.get_metadata_value(activity));
105+
if matches!(diff_activity, DiffActivity::Dualv) {
106+
let next_outer_arg = outer_args[outer_pos + 1];
107+
let elem_bytes_size: u64 = match inputs[activity_pos + 1] {
108+
DiffActivity::FakeActivitySize(Some(s)) => s.into(),
109+
_ => bug!("incorrect Dualv handling recognized."),
110+
};
111+
// stride: sizeof(T) * n_elems.
112+
// n_elems is the next integer.
113+
// Now we multiply `4 * next_outer_arg` to get the stride.
114+
let mul = unsafe {
115+
llvm::LLVMBuildMul(
116+
builder.llbuilder,
117+
cx.get_const_i64(elem_bytes_size),
118+
next_outer_arg,
119+
UNNAMED,
120+
)
121+
};
122+
args.push(mul);
123+
}
100124
args.push(outer_arg);
101125
if duplicated {
102126
// We know that duplicated args by construction have a following argument,
@@ -114,7 +138,7 @@ fn match_args_from_caller_to_enzyme<'ll>(
114138
} else {
115139
let next_activity = inputs[activity_pos + 1];
116140
// We analyze the MIR types and add this dummy activity if we visit a slice.
117-
next_activity == DiffActivity::FakeActivitySize
141+
matches!(next_activity, DiffActivity::FakeActivitySize(_))
118142
}
119143
};
120144
if slice {
@@ -125,7 +149,10 @@ fn match_args_from_caller_to_enzyme<'ll>(
125149
// int2 >= int1, which means the shadow vector is large enough to store the gradient.
126150
assert_eq!(cx.type_kind(next_outer_ty), TypeKind::Integer);
127151

128-
for i in 0..(width as usize) {
152+
let iterations =
153+
if matches!(diff_activity, DiffActivity::Dualv) { 1 } else { width as usize };
154+
155+
for i in 0..iterations {
129156
let next_outer_arg2 = outer_args[outer_pos + 2 * (i + 1)];
130157
let next_outer_ty2 = cx.val_ty(next_outer_arg2);
131158
assert_eq!(cx.type_kind(next_outer_ty2), TypeKind::Pointer);
@@ -136,7 +163,7 @@ fn match_args_from_caller_to_enzyme<'ll>(
136163
}
137164
args.push(cx.get_metadata_value(enzyme_const));
138165
args.push(next_outer_arg);
139-
outer_pos += 2 + 2 * width as usize;
166+
outer_pos += 2 + 2 * iterations;
140167
activity_pos += 2;
141168
} else {
142169
// A duplicated pointer will have the following two outer_fn arguments:
@@ -360,6 +387,7 @@ fn generate_enzyme_call<'ll>(
360387
let outer_args: Vec<&llvm::Value> = get_params(outer_fn);
361388
match_args_from_caller_to_enzyme(
362389
&cx,
390+
&builder,
363391
attrs.width,
364392
&mut args,
365393
&attrs.input_activity,

compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>(
247247
StubInfo { metadata, unique_type_id }
248248
}
249249

250+
struct AdtStackPopGuard<'ll, 'tcx, 'a> {
251+
cx: &'a CodegenCx<'ll, 'tcx>,
252+
}
253+
254+
impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> {
255+
fn drop(&mut self) {
256+
debug_context(self.cx).adt_stack.borrow_mut().pop();
257+
}
258+
}
259+
250260
/// This function enables creating debuginfo nodes that can recursively refer to themselves.
251261
/// It will first insert the given stub into the type map and only then execute the `members`
252262
/// and `generics` closures passed in. These closures have access to the stub so they can
@@ -261,6 +271,44 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
261271
) -> DINodeCreationResult<'ll> {
262272
assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
263273

274+
let mut _adt_stack_pop_guard = None;
275+
if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id
276+
&& let ty::Adt(adt_def, args) = ty.kind()
277+
{
278+
let def_id = adt_def.did();
279+
// If any sub type reference the original type definition and the sub type has a type
280+
// parameter that strictly contains the original parameter, the original type is a recursive
281+
// type that can expanding indefinitely. Example,
282+
// ```
283+
// enum Recursive<T> {
284+
// Recurse(*const Recursive<Wrap<T>>),
285+
// Item(T),
286+
// }
287+
// ```
288+
let is_expanding_recursive =
289+
debug_context(cx).adt_stack.borrow().iter().any(|(parent_def_id, parent_args)| {
290+
if def_id == *parent_def_id {
291+
args.iter().zip(parent_args.iter()).any(|(arg, parent_arg)| {
292+
if let (Some(arg), Some(parent_arg)) = (arg.as_type(), parent_arg.as_type())
293+
{
294+
arg != parent_arg && arg.contains(parent_arg)
295+
} else {
296+
false
297+
}
298+
})
299+
} else {
300+
false
301+
}
302+
});
303+
if is_expanding_recursive {
304+
// FIXME: indicate that this is an expanding recursive type in stub metadata?
305+
return DINodeCreationResult::new(stub_info.metadata, false);
306+
} else {
307+
debug_context(cx).adt_stack.borrow_mut().push((def_id, args));
308+
_adt_stack_pop_guard = Some(AdtStackPopGuard { cx });
309+
}
310+
}
311+
264312
debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
265313

266314
let members: SmallVec<_> =

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
6666
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
6767

6868
type_map: metadata::TypeMap<'ll, 'tcx>,
69+
adt_stack: RefCell<Vec<(DefId, GenericArgsRef<'tcx>)>>,
6970
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
7071
recursion_marker_type: OnceCell<&'ll DIType>,
7172
}
@@ -80,6 +81,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
8081
builder,
8182
created_files: Default::default(),
8283
type_map: Default::default(),
84+
adt_stack: Default::default(),
8385
namespace_map: RefCell::new(Default::default()),
8486
recursion_marker_type: OnceCell::new(),
8587
}

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::check_consts::is_fn_or_trait_safe_to_expose_on_stable;
3434
use crate::errors;
3535

3636
type QualifResults<'mir, 'tcx, Q> =
37-
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
37+
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'tcx, Q>>;
3838

3939
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
4040
enum ConstConditionsHold {

0 commit comments

Comments
 (0)