Skip to content

Commit 6c8bec9

Browse files
committed
impl drop for PreloadMut, which must returned the mutated value
1 parent fae2f07 commit 6c8bec9

5 files changed

Lines changed: 123 additions & 3 deletions

File tree

compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ pub(crate) fn gen_define_handling<'ll>(
446446
let valid_begin_mappings = MappingFlags::TO | MappingFlags::LITERAL | MappingFlags::IMPLICIT;
447447
let transfer_to: Vec<u64> =
448448
transfer.iter().map(|m| m.intersection(valid_begin_mappings).bits()).collect();
449+
dbg!(&transfer);
449450
let transfer_from: Vec<u64> =
450451
transfer.iter().map(|m| m.intersection(MappingFlags::FROM).bits()).collect();
451452
let valid_kernel_mappings = MappingFlags::LITERAL | MappingFlags::IMPLICIT;
@@ -469,6 +470,7 @@ pub(crate) fn gen_define_handling<'ll>(
469470
add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.begin"), &transfer_to);
470471
let memtransfer_kernel =
471472
add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.kernel"), &transfer_kernel);
473+
dbg!(&transfer_from);
472474
let memtransfer_end =
473475
add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.end"), &transfer_from);
474476

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_hir::def_id::LOCAL_CRATE;
1919
use rustc_hir::find_attr;
2020
use rustc_middle::mir::BinOp;
2121
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
22-
use rustc_middle::ty::offload_meta::OffloadMetadata;
22+
use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata};
2323
use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv};
2424
use rustc_middle::{bug, span_bug};
2525
use rustc_session::config::CrateType;
@@ -188,6 +188,17 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
188188
codegen_offload_preload(self, tcx, instance, args);
189189
}
190190

191+
fn codegen_offload_preload_mut_drop(
192+
&mut self,
193+
preload_ty: Ty<'tcx>,
194+
place: PlaceRef<'tcx, &'ll llvm::Value>,
195+
) {
196+
let tcx = self.tcx;
197+
dbg!("Dropping PreloadMut; emit offload end mapper");
198+
199+
codegen_offload_preload_mut_drop(self, tcx, preload_ty, place);
200+
}
201+
191202
fn codegen_intrinsic_call(
192203
&mut self,
193204
instance: ty::Instance<'tcx>,
@@ -1911,6 +1922,83 @@ fn codegen_autodiff<'ll, 'tcx>(
19111922
);
19121923
}
19131924

1925+
fn codegen_offload_preload_mut_drop<'ll, 'tcx>(
1926+
bx: &mut Builder<'_, 'll, 'tcx>,
1927+
tcx: TyCtxt<'tcx>,
1928+
preload_ty: Ty<'tcx>,
1929+
place: PlaceRef<'tcx, &'ll llvm::Value>,
1930+
) {
1931+
let cx = bx.cx;
1932+
dbg!("Starting the PreloadMut drop handling!");
1933+
// PreloadMut<'a, T> -> extract T.
1934+
let ty::Adt(_adt_def, generic_args) = preload_ty.kind() else {
1935+
bug!("expected PreloadMut ADT, got {preload_ty:?}");
1936+
};
1937+
1938+
// This should be the `T` parameter of PreloadMut<'a, T>.
1939+
// If this indexes the lifetime in your tree, use the correct type arg index
1940+
// or `generic_args.types().next().unwrap()`.
1941+
let pointee_ty: Ty<'tcx> =
1942+
generic_args.types().next().unwrap_or_else(|| bug!("PreloadMut without type parameter"));
1943+
1944+
// Load field 0: `cpu_ptr: *mut T`.
1945+
let cpu_ptr_place = place.project_field(bx, 0);
1946+
dbg!(&cpu_ptr_place);
1947+
let cpu_ptr_operand = bx.load_operand(cpu_ptr_place);
1948+
dbg!(&cpu_ptr_operand);
1949+
1950+
let args: Vec<&'ll Value> = match cpu_ptr_operand.val {
1951+
OperandValue::Immediate(ptr) => vec![ptr],
1952+
OperandValue::Pair(_data, _meta) => {
1953+
bug!("unsized PreloadMut drop not handled yet")
1954+
}
1955+
_ => bug!("unexpected PreloadMut cpu_ptr operand"),
1956+
};
1957+
1958+
let mut meta = OffloadMetadata::from_ty(tcx, pointee_ty);
1959+
// We end a mut Mapper. Unless the user never mutated a mut variable passed in a mutable way, we
1960+
// must return it from the device to update the host version. If they never mutated it, they
1961+
// surely got a clippy or rustc warning, so it's up to them for wasting time.
1962+
meta.mode |= MappingFlags::FROM;
1963+
dbg!(&meta);
1964+
let metadata: &[OffloadMetadata; 1] = &[meta];
1965+
1966+
let types: &Type = cx.layout_of(pointee_ty).llvm_type(cx);
1967+
1968+
let offload_globals_ref = cx.offload_globals.borrow();
1969+
let offload_globals = match offload_globals_ref.as_ref() {
1970+
Some(globals) => globals,
1971+
None => {
1972+
dbg!("Have to initialize offload? This is a bug!");
1973+
return;
1974+
}
1975+
};
1976+
1977+
let target_symbol = cx.generate_local_symbol_name("");
1978+
dbg!("done for now");
1979+
let offload_data = gen_define_handling(&cx, metadata, target_symbol, offload_globals);
1980+
let has_dynamic = metadata.iter().any(|m| !matches!(m.payload_size, OffloadSize::Static(_)));
1981+
let (ty, ty2, a1, a2, a4) = crate::builder::gpu_helper::preper_datatransfers(
1982+
bx,
1983+
&args,
1984+
&[types],
1985+
offload_data.offload_sizes,
1986+
metadata,
1987+
has_dynamic,
1988+
);
1989+
let geps = crate::builder::gpu_helper::get_geps(bx, ty, ty2, a1, a2, a4, has_dynamic);
1990+
1991+
crate::builder::gpu_helper::generate_mapper_call(
1992+
bx,
1993+
geps,
1994+
offload_data.memtransfer_end,
1995+
offload_globals.end_mapper,
1996+
offload_globals.mapper_fn_ty,
1997+
1,
1998+
offload_globals.ident_t_global,
1999+
);
2000+
}
2001+
19142002
// For each PreLoad *call*, we now use some of our previous declared globals to move data to the gpu.
19152003
// For now, we only handle the data transfer part of it. Consecutive calls become a no-op on the
19162004
// LLVM side.

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER;
99
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
1010
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1111
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
12-
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
12+
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt};
1313
use rustc_middle::{bug, span_bug};
1414
use rustc_session::config::OptLevel;
1515
use rustc_span::{Span, Spanned};
@@ -27,6 +27,14 @@ use crate::mir::IntrinsicResult;
2727
use crate::traits::*;
2828
use crate::{MemFlags, meth};
2929

30+
fn is_preload_mut_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
31+
let ty::Adt(adt_def, _) = ty.kind() else {
32+
return false;
33+
};
34+
35+
Some(adt_def.did()) == tcx.lang_items().preload_mut_type()
36+
}
37+
3038
// Indicates if we are in the middle of merging a BB's successor into it. This
3139
// can happen when BB jumps directly to its successor and the successor has no
3240
// other predecessors.
@@ -604,6 +612,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
604612
) -> MergingSucc {
605613
let ty = location.ty(self.mir, bx.tcx()).ty;
606614
let ty = self.monomorphize(ty);
615+
616+
if is_preload_mut_type(bx.tcx(), ty) {
617+
let place = self.codegen_place(bx, location.as_ref());
618+
619+
bx.codegen_offload_preload_mut_drop(ty, place);
620+
}
607621
let drop_fn = Instance::resolve_drop_glue(bx.tcx(), ty);
608622

609623
if let ty::InstanceKind::DropGlue(_, None) = drop_fn.def {

compiler/rustc_codegen_ssa/src/traits/intrinsic.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::BackendTypes;
55
use crate::RetagInfo;
66
use crate::mir::IntrinsicResult;
77
use crate::mir::operand::OperandRef;
8-
use crate::mir::place::PlaceValue;
8+
use crate::mir::place::{PlaceRef, PlaceValue};
99

1010
pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
1111
/// Higher-level interface to emitting calls to intrinsics
@@ -38,6 +38,12 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
3838
is_mut: bool,
3939
);
4040

41+
fn codegen_offload_preload_mut_drop(
42+
&mut self,
43+
preload_ty: ty::Ty<'tcx>,
44+
place: PlaceRef<'tcx, Self::Value>,
45+
);
46+
4147
fn codegen_llvm_intrinsic_call(
4248
&mut self,
4349
instance: ty::Instance<'tcx>,

library/core/src/offload/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,13 @@ pub fn preload<'a, T: ?Sized>(x: &'a T) -> Preload<'a, T> {
3131
pub fn preload_mut<'a, T: ?Sized>(x: &'a mut T) -> PreloadMut<'a, T> {
3232
PreloadMut { cpu_ptr: x as *mut T, _marker: PhantomData }
3333
}
34+
35+
impl<T: ?Sized> Drop for PreloadMut<'_, T> {
36+
fn drop(&mut self) {
37+
// Intentionally empty.
38+
//
39+
// This exists so MIR creates Drop terminators for PreloadMut.
40+
// rustc codegen intercepts those terminators and emits the
41+
// offload return mapper.
42+
}
43+
}

0 commit comments

Comments
 (0)