Skip to content

Commit bf5d369

Browse files
committed
intermediate commit (no compile)
1 parent 6a7c730 commit bf5d369

File tree

12 files changed

+134
-46
lines changed

12 files changed

+134
-46
lines changed

compiler/rustc_const_eval/src/const_eval/dummy_machine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
168168
})
169169
}
170170

171-
fn expose_ptr(
171+
fn expose_provenance(
172172
_ecx: &mut InterpCx<'tcx, Self>,
173-
_ptr: interpret::Pointer<Self::Provenance>,
173+
_provenance: Self::Provenance,
174174
) -> interpret::InterpResult<'tcx> {
175175
unimplemented!()
176176
}

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
586586
}
587587

588588
#[inline(always)]
589-
fn expose_ptr(_ecx: &mut InterpCx<'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
589+
fn expose_provenance(_ecx: &mut InterpCx<'tcx, Self>, _provenance: Self::Provenance) -> InterpResult<'tcx> {
590590
// This is only reachable with -Zunleash-the-miri-inside-of-you.
591591
throw_unsup_format!("exposing pointers is not possible at compile-time")
592592
}

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
238238
let scalar = src.to_scalar();
239239
let ptr = scalar.to_pointer(self)?;
240240
match ptr.into_pointer_or_addr() {
241-
Ok(ptr) => M::expose_ptr(self, ptr)?,
241+
Ok(ptr) => M::expose_provenance(self, ptr.provenance)?,
242242
Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP.
243243
};
244244
interp_ok(ImmTy::from_scalar(

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,9 @@ pub trait Machine<'tcx>: Sized {
329329

330330
/// Marks a pointer as exposed, allowing it's provenance
331331
/// to be recovered. "Pointer-to-int cast"
332-
fn expose_ptr(
332+
fn expose_provenance(
333333
ecx: &mut InterpCx<'tcx, Self>,
334-
ptr: Pointer<Self::Provenance>,
334+
provenance: Self::Provenance,
335335
) -> InterpResult<'tcx>;
336336

337337
/// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -943,25 +943,37 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
943943
self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not;
944944
interp_ok(())
945945
}
946-
947-
pub fn alloc_mark_init_rec(&mut self, id: AllocId) -> InterpResult<'tcx> {
948-
let mut reachable = rustc_data_structures::fx::FxHashSet::default();
946+
947+
pub fn prepare_for_native_call(&mut self, id: AllocId, initial_prov: M) -> InterpResult<'tcx> {
948+
let mut done = rustc_data_structures::fx::FxHashSet::default();
949949
let mut todo = vec![id];
950950
while let Some(id) = todo.pop() {
951-
if reachable.insert(id) {
951+
if done.insert(id) {
952952
// This is a new allocation, add the allocation it points to `todo`.
953-
if let Ok((alloc, _)) = self.get_alloc_raw_mut(id) {
954-
let range = AllocRange { start: Size::ZERO, size: Size::from_bytes(alloc.len()) };
955-
alloc
956-
.write_zero_if_uninit(range)
953+
let (_size, _align, kind, mutability) = self.get_alloc_info(id); // TODO: Rebasing will give me the mutaility.
954+
955+
// If there is no data behind this pointer, skip this.
956+
if !matches!(kind, AllocKind::LiveData) {
957+
continue;
958+
}
959+
960+
let alloc = self.get_alloc_raw(id)?;
961+
for prov in alloc.provenance().provenances() {
962+
M::expose_provenance(self, prov)?; // TODO: Is this right?
963+
if let Some(id) = prov.get_alloc_id() {
964+
todo.push(id);
965+
}
966+
}
967+
968+
// Prepare for possible write from native code if mutable.
969+
if mutability.is_mut() {
970+
self.get_alloc_raw_mut(id)?
971+
.prepare_for_native_call()
957972
.map_err(|e| e.to_interp_error(id))?;
958-
todo.extend(
959-
alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()),
960-
);
961973
}
962974
}
963975
}
964-
Ok(())
976+
interp_ok(())
965977
}
966978

967979
/// Create a lazy debug printer that prints the given allocation and all allocations it points

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,23 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
643643
Ok(())
644644
}
645645

646-
/// Write zeroes to the unitialized memory within the given memory range.
647-
pub fn write_zero_if_uninit(&mut self, range: AllocRange) -> AllocResult {
648-
self.mark_init(range, true); // TODO: Write zeroes?
646+
/// Initialize all previously uninitialized bytes in the entire allocation, and set
647+
/// provenance of everything to `Wildcard`
648+
pub fn prepare_for_native_call(&mut self) -> AllocResult {
649+
let full_range = AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) };
650+
// Overwrite uninitialized bytes.
651+
for chunk in self.init_mask.range_as_init_chunks(full_range) {
652+
if !chunk.is_init() {
653+
let uninit_bytes = &mut self.bytes[chunk.range().start.bytes_usize()..chunk.range().end.bytes_usize()];
654+
uninit_bytes.fill(0);
655+
}
656+
}
657+
// Mark everything as initialized now.
658+
self.mark_init(full_range, true);
659+
660+
// Set provenance of all bytes to wildcard.
661+
self.provenance.write_wildcards(self.len());
662+
649663
Ok(())
650664
}
651665

compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,15 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
195195

196196
Ok(())
197197
}
198+
199+
pub fn write_wildcards(&mut self, _alloc_size: usize) {
200+
// We can only write wildcards in Miri.
201+
assert!(Prov::OFFSET_IS_ADDR, "writing wildcard provenance is not supported when `OFFSET_IS_ADDR` is false");
202+
let _wildcard = Prov::WILDCARD.unwrap();
203+
204+
// TODO: This.
205+
206+
}
198207
}
199208

200209
/// A partial, owned list of provenance to transfer into another allocation.

compiler/rustc_middle/src/mir/interpret/pointer.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
6666
/// pointer, and implement ptr-to-int transmutation by stripping provenance.
6767
const OFFSET_IS_ADDR: bool;
6868

69+
/// If wildcard provenance is implemented, contains the unique, general wildcard provenance variant.
70+
const WILDCARD: Option<Self>;
71+
6972
/// Determines how a pointer should be printed.
7073
fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result;
7174

@@ -168,6 +171,9 @@ impl Provenance for CtfeProvenance {
168171
// so ptr-to-int casts are not possible (since we do not know the global physical offset).
169172
const OFFSET_IS_ADDR: bool = false;
170173

174+
// `CtfeProvenance` does not implement wildcard provenance.
175+
const WILDCARD: Option<Self> = None;
176+
171177
fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172178
// Print AllocId.
173179
fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag
@@ -197,6 +203,9 @@ impl Provenance for AllocId {
197203
// so ptr-to-int casts are not possible (since we do not know the global physical offset).
198204
const OFFSET_IS_ADDR: bool = false;
199205

206+
// `AllocId` does not implement wildcard provenance.
207+
const WILDCARD: Option<Self> = None;
208+
200209
fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201210
// Forward `alternate` flag to `alloc_id` printing.
202211
if f.alternate() {

src/tools/miri/src/machine.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ impl interpret::Provenance for Provenance {
268268
/// We use absolute addresses in the `offset` of a `StrictPointer`.
269269
const OFFSET_IS_ADDR: bool = true;
270270

271+
/// Miri implements wildcard provenance.
272+
const WILDCARD: Option<Self> = Some(Provenance::Wildcard);
273+
271274
fn get_alloc_id(self) -> Option<AllocId> {
272275
match self {
273276
Provenance::Concrete { alloc_id, .. } => Some(alloc_id),
@@ -1241,8 +1244,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
12411244
/// Called on `ptr as usize` casts.
12421245
/// (Actually computing the resulting `usize` doesn't need machine help,
12431246
/// that's just `Scalar::try_to_int`.)
1244-
fn expose_ptr(ecx: &mut InterpCx<'tcx, Self>, ptr: StrictPointer) -> InterpResult<'tcx> {
1245-
match ptr.provenance {
1247+
fn expose_provenance(ecx: &mut InterpCx<'tcx, Self>, provenance: Self::Provenance) -> InterpResult<'tcx> {
1248+
match provenance {
12461249
Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
12471250
Provenance::Wildcard => {
12481251
// No need to do anything for wildcard pointers as

src/tools/miri/src/shims/native_lib.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
153153
throw_unsup_format!("only scalar argument types are support for native calls")
154154
}
155155
let imm = this.read_immediate(arg)?;
156-
if matches!(arg.layout.ty.kind(), ty::RawPtr(_, rustc_ast::Mutability::Mut)) {
157-
let ptr = this.read_pointer(&imm)?;
158-
let Ok((alloc_id, _size, _prov_extra)) = this.ptr_try_get_alloc_id(ptr, 0) else {
159-
todo!(); // TODO: Handle absolute-address-returned case.
156+
libffi_args.push(imm_to_carg(&imm, this)?);
157+
if matches!(arg.layout.ty.kind(), ty::RawPtr(..)) {
158+
let ptr = imm.to_scalar().to_pointer(self)?;
159+
// We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance.
160+
let Ok(alloc_id) = ptr.provenance.and_then(|prov| prov.get_alloc_id()) else {
161+
// Pointer without provenance may access any memory.
162+
continue;
160163
};
161-
this.alloc_mark_init_rec(alloc_id)?;
164+
this.prepare_for_native_call(alloc_id, ptr.provenance)?;
165+
// TODO: Write tests for (forgetting to) expose: -initial allocation -recursively all allocations -unexposed pointers.
162166
}
163-
libffi_args.push(imm_to_carg(imm, this)?);
164167
}
165168

166-
// TODO: Directly collect into correct Vec? -- lifetime issues.
167169
// Convert them to `libffi::high::Arg` type.
168170
let libffi_args = libffi_args
169171
.iter()
@@ -229,7 +231,7 @@ impl<'a> CArg {
229231

230232
/// Extract the scalar value from the result of reading a scalar from the machine,
231233
/// and convert it to a `CArg`.
232-
fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> {
234+
fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> {
233235
interp_ok(match v.layout.ty.kind() {
234236
// If the primitive provided can be converted to a type matching the type pattern
235237
// then create a `CArg` of this primitive value with the corresponding `CArg` constructor.

0 commit comments

Comments
 (0)